[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