[CRIU] [PATCH] test: inotify00 -- Rework test
Cyrill Gorcunov
gorcunov at openvz.org
Wed Sep 3 12:01:13 PDT 2014
To show which events are coming and flush
events before dump as required by new fsnotify mode.
| Execute zdtm/live/static/inotify00
| ./inotify00 --pidfile=inotify00.pid --outfile=inotify00.out
| Dump 8212
| Restore
| Check results 8212
| 23:00:09.842: 8212: unlink 01 : event 0x20 -> IN_OPEN
| 23:00:09.842: 8212: unlink 01 : event 0x20 -> IN_OPEN
| 23:00:09.842: 8212: unlink 01 : event 0x20 -> IN_OPEN
| 23:00:09.842: 8212: unlink 01 : event 0x20 -> IN_OPEN
| 23:00:09.842: 8212: unlink 01 : event 0x4 -> IN_ATTRIB
| 23:00:09.842: 8212: unlink 01 : event 0x200 -> IN_DELETE
| 23:00:09.842: 8212: unlink 01 : read 6 events
| 23:00:09.842: 8212: unlink 02 : event 0x4 -> IN_ATTRIB
| 23:00:09.842: 8212: unlink 02 : event 0x200 -> IN_DELETE
| 23:00:09.842: 8212: unlink 02 : event 0x8 -> IN_CLOSE_WRITE
| 23:00:09.842: 8212: unlink 02 : event 0x8 -> IN_CLOSE_WRITE
| 23:00:09.842: 8212: unlink 02 : event 0x400 -> IN_DELETE_SELF
| 23:00:09.842: 8212: unlink 02 : event 0x8000 -> IN_IGNORED
| 23:00:09.842: 8212: unlink 02 : read 6 events
| 23:00:09.924: 8212: after : event 0x40000010 -> IN_CLOSE_NOWRITE | IN_ISDIR
| 23:00:09.924: 8212: after : event 0x100 -> IN_CREATE
| 23:00:09.925: 8212: after : event 0x20 -> IN_OPEN
| 23:00:09.925: 8212: after : event 0x200 -> IN_DELETE
| 23:00:09.925: 8212: after : event 0x100 -> IN_CREATE
| 23:00:09.925: 8212: after : event 0x20 -> IN_OPEN
| 23:00:09.925: 8212: after : event 0x200 -> IN_DELETE
| 23:00:09.925: 8212: after : event 0x200 -> IN_DELETE
| 23:00:09.925: 8212: after : event 0x8 -> IN_CLOSE_WRITE
| 23:00:09.925: 8212: after : event 0x40000020 -> IN_OPEN | IN_ISDIR
| 23:00:09.925: 8212: after : event 0x40000010 -> IN_CLOSE_NOWRITE | IN_ISDIR
| 23:00:09.925: 8212: after : read 11 events
| 23:00:09.925: 8212: PASS
| Test: zdtm/live/static/inotify00, Result: PASS
| ZDTM tests PASS.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
test/zdtm/live/static/inotify00.c | 254 ++++++++++++++++++++++++++++++++++----
1 file changed, 232 insertions(+), 22 deletions(-)
diff --git a/test/zdtm/live/static/inotify00.c b/test/zdtm/live/static/inotify00.c
index 587408cda5bd..9b6e9beb4301 100644
--- a/test/zdtm/live/static/inotify00.c
+++ b/test/zdtm/live/static/inotify00.c
@@ -12,63 +12,273 @@
#include <sys/inotify.h>
#include <unistd.h>
#include <stdlib.h>
+#include <dirent.h>
#include "zdtmtst.h"
const char *test_doc = "Check for inotify delivery";
const char *test_author = "Cyrill Gorcunov <gorcunov at openvz.org>";
-const char path[] = "inotify-removed";
+#define TEST_DIR "inotify-test"
+#define TEST_FILE "inotify-removed"
+#define TEST_LINK "inotify-hardlink"
+#define TEST_FILE_PATH TEST_DIR "/" TEST_FILE
+#define TEST_LINK_PATH TEST_DIR "/" TEST_LINK
#define BUFF_SIZE ((sizeof(struct inotify_event) + PATH_MAX))
+static int rmdir_force(const char *directory)
+{
+ DIR *dir = opendir(directory);
+ char path[PATH_MAX];
+ struct dirent *d;
+
+ if (!dir) {
+ if (errno == ENOENT)
+ return 0;
+ err("Can't open %s", directory);
+ return -1;
+ }
+
+ while ((d = readdir(dir))) {
+ struct stat st;
+
+ if(!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ snprintf(path, sizeof(path), "%s/%s", directory, d->d_name);
+ if (stat(path, &st)) {
+ if (unlink(path)) {
+ err("Can't stat/unlink %s", path);
+ goto err;
+ }
+ continue;
+ } else {
+ if (S_ISDIR(st.st_mode)) {
+ if (rmdir_force(path)) {
+ err("Can't remove subdir %s", path);
+ goto err;
+ }
+ }
+ }
+
+ if (unlink(path)) {
+ err("Can't unlink %s", path);
+ goto err;
+ }
+ }
+
+ closedir(dir);
+ if (rmdir(directory)) {
+ err("Can't unlink %s", directory);
+ return -1;
+ }
+ return 0;
+err:
+ closedir(dir);
+ return -1;
+}
+
+static void decode_event_mask(char *buf, size_t size, unsigned int mask)
+{
+ static const char *names[32] = {
+ [ 0] = "IN_ACCESS",
+ [ 1] = "IN_MODIFY",
+ [ 2] = "IN_ATTRIB",
+ [ 3] = "IN_CLOSE_WRITE",
+ [ 4] = "IN_CLOSE_NOWRITE",
+ [ 5] = "IN_OPEN",
+ [ 6] = "IN_MOVED_FROM",
+ [ 7] = "IN_MOVED_TO",
+ [ 8] = "IN_CREATE",
+ [ 9] = "IN_DELETE",
+ [10] = "IN_DELETE_SELF",
+ [11] = "IN_MOVE_SELF",
+
+ [13] = "IN_UNMOUNT",
+ [14] = "IN_Q_OVERFLOW",
+ [15] = "IN_IGNORED",
+
+ [24] = "IN_ONLYDIR",
+ [25] = "IN_DONT_FOLLOW",
+ [26] = "IN_EXCL_UNLINK",
+
+ [29] = "IN_MASK_ADD",
+ [30] = "IN_ISDIR",
+ [31] = "IN_ONESHOT",
+ };
+
+ size_t i, j;
+
+ memset(buf, 0, size);
+ for (i = 0, j = 0; i < 32 && j < size; i++) {
+ if (!(mask & (1u << i)))
+ continue;
+ if (j)
+ j += snprintf(&buf[j], size - j, " | %s", names[i]);
+ else
+ j += snprintf(&buf[j], size - j, "%s", names[i]);
+ }
+}
+
+static int inotify_read_events(char *prefix, int inotify_fd, unsigned int *expected)
+{
+ struct inotify_event *event;
+ char buf[sizeof(*event) * 8];
+ int ret, off, n = 0;
+
+ while (1) {
+ ret = read(inotify_fd, buf, sizeof(buf));
+ if (ret < 0) {
+ if (errno != EAGAIN) {
+ err("Can't read inotify queue");
+ return -1;
+ } else {
+ ret = 0;
+ goto out;
+ }
+ } else if (ret == 0)
+ break;
+
+ for (off = 0; off < ret; n++, off += sizeof(*event) + event->len) {
+ char emask[128];
+
+ event = (void *)(buf + off);
+ decode_event_mask(emask, sizeof(emask), event->mask);
+ test_msg("\t%-16s: event %#10x -> %s\n",
+ prefix, event->mask, emask);
+ if (expected)
+ *expected &= ~event->mask;
+ }
+ }
+
+out:
+ test_msg("\t%-16s: read %2d events\n", prefix, n);
+ return ret;
+}
+
int main (int argc, char *argv[])
{
- char buf[BUFF_SIZE];
- int fd, wd, deleted, wd_deleted;
+ int fd, link_fd, real_fd;
+ unsigned int emask;
test_init(argc, argv);
+ if (rmdir_force(TEST_DIR))
+ exit(1);
+
+ if (mkdir(TEST_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
+ err("Can't create directory %s", TEST_DIR);
+ exit(1);
+ }
+
fd = inotify_init1(IN_NONBLOCK);
if (fd < 0) {
- fail("inotify_init failed");
+ err("inotify_init failed");
+ exit(1);
+ }
+
+ if (open(TEST_FILE_PATH, O_CREAT | O_TRUNC) < 0) {
+ err("inotify_init failed");
exit(1);
}
- wd = 0;
- wd |= inotify_add_watch(fd, "/", IN_ALL_EVENTS);
- if (wd < 0) {
- fail("inotify_add_watch failed");
+ if (chdir(TEST_DIR)) {
+ err("Can't step into %s", TEST_DIR);
+ exit(1);
+ } else {
+ if (link(TEST_FILE, TEST_LINK)) {
+ err("Can't link %s -> %s", TEST_LINK_PATH, TEST_FILE_PATH);
+ exit(1);
+ }
+ }
+
+ if (chdir("..")) {
+ err("Can't return from %s", TEST_DIR);
exit(1);
}
- deleted = open(path, O_CREAT | O_TRUNC);
- if (deleted < 0) {
- fail("inotify_init failed");
+ if (inotify_add_watch(fd, TEST_DIR, IN_ALL_EVENTS) < 0) {
+ err("inotify_add_watch failed");
exit(1);
}
- wd_deleted = inotify_add_watch(fd, path, IN_ALL_EVENTS);
- if (wd_deleted < 0) {
- fail("inotify_add_watch failed");
+ if (inotify_add_watch(fd, TEST_FILE_PATH, IN_ALL_EVENTS) < 0) {
+ err("inotify_add_watch failed");
exit(1);
}
- if (unlink(path)) {
- fail("can't unlink %s\n", path);
+ if (inotify_add_watch(fd, TEST_LINK_PATH, IN_ALL_EVENTS) < 0) {
+ err("inotify_add_watch failed");
+ exit(1);
+ }
+
+ link_fd = open(TEST_LINK_PATH, O_RDWR);
+ if (link_fd < 0) {
+ err("Can't open link");
+ exit(1);
+ }
+
+ real_fd = open(TEST_FILE_PATH, O_RDWR);
+ if (real_fd < 0) {
+ err("Can't open real");
+ exit(1);
+ }
+
+ /*
+ * At this moment we have a file inside testing
+ * directory and a hardlink to it. The file and
+ * hardlink are opened.
+ */
+
+ if (unlink(TEST_LINK_PATH)) {
+ err("can't unlink %s\n", TEST_LINK_PATH);
+ exit(1);
+ }
+
+ emask = IN_OPEN | IN_DELETE;
+ inotify_read_events("unlink 01", fd, &emask);
+ if (emask) {
+ char emask_bits[128];
+ decode_event_mask(emask_bits, sizeof(emask_bits), emask);
+ err("Unhandled events in emask %#x -> %s",
+ emask, emask_bits);
+ exit(1);
+ }
+
+ if (unlink(TEST_FILE_PATH)) {
+ err("can't unlink %s\n", TEST_FILE_PATH);
+ exit(1);
+ }
+
+ close(link_fd);
+
+ emask = IN_DELETE | IN_CLOSE_WRITE | IN_DELETE_SELF;
+ inotify_read_events("unlink 02", fd, &emask);
+ if (emask) {
+ char emask_bits[128];
+ decode_event_mask(emask_bits, sizeof(emask_bits), emask);
+ err("Unhandled events in emask %#x -> %s",
+ emask, emask_bits);
exit(1);
}
test_daemon();
test_waitsig();
- wd = open("/", O_RDONLY);
- if (read(fd, buf, sizeof(buf)) > 0) {
+ close(real_fd);
+
+ rmdir_force(TEST_DIR);
+ emask = IN_DELETE | IN_CLOSE_WRITE;
+ inotify_read_events("after", fd, &emask);
+ if (emask) {
+ char emask_bits[128];
+ decode_event_mask(emask_bits, sizeof(emask_bits), emask);
+ fail("Unhandled events in emask %#x -> %s",
+ emask, emask_bits);
+ return 1;
+ } else
pass();
- } else {
- fail("No events in queue");
- exit(1);
- }
return 0;
}
--
1.9.3
More information about the CRIU
mailing list