[PATCH] test: inotify00 -- Rework test, v2

Cyrill Gorcunov gorcunov at openvz.org
Wed Sep 3 11:59:38 PDT 2014


To show which events are coming and flush events before dump as required by new fsnotify mode.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 test/zdtm/live/static/Makefile    |   2 +-
 test/zdtm/live/static/inotify00.c | 193 +++++++++++++++++++++++++++++++++-----
 2 files changed, 172 insertions(+), 23 deletions(-)

diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index e96e71110e76..e07920106518 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -77,7 +77,6 @@ TST_NOFILE	=				\
 		proc-self			\
 		eventfs00			\
 		signalfd00			\
-		inotify00			\
 		inotify_irmap			\
 		fanotify00			\
 		uptime_grow			\
@@ -166,6 +165,7 @@ TST_DIR		=				\
 		overmount_sock			\
 		tempfs				\
 		bind-mount			\
+		inotify00			\
 		cgroup00			\
 		rmdir_open			\
 		cgroup01			\
diff --git a/test/zdtm/live/static/inotify00.c b/test/zdtm/live/static/inotify00.c
index 587408cda5bd..2e25a663b718 100644
--- a/test/zdtm/live/static/inotify00.c
+++ b/test/zdtm/live/static/inotify00.c
@@ -12,63 +12,212 @@
 #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";
+char *dirname;
+TEST_OPTION(dirname, string, "directory name", 1);
+
+#define TEST_FILE	"inotify-removed"
+#define TEST_LINK	"inotify-hardlink"
 
 #define BUFF_SIZE ((sizeof(struct inotify_event) + PATH_MAX))
 
+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[BUFF_SIZE * 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;
+	unsigned int mask = IN_DELETE | IN_CLOSE_WRITE | IN_DELETE_SELF;
+	char test_link_path[PATH_MAX], test_file_path[PATH_MAX];
+	int fd, link_fd, real_fd;
+	unsigned int emask;
 
 	test_init(argc, argv);
 
 	fd = inotify_init1(IN_NONBLOCK);
 	if (fd < 0) {
-		fail("inotify_init failed");
+		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 (mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
+		err("Can't create directory %s", dirname);
 		exit(1);
 	}
 
-	deleted = open(path, O_CREAT | O_TRUNC);
-	if (deleted < 0) {
-		fail("inotify_init failed");
+	snprintf(test_link_path, sizeof(test_link_path), "%s/%s", dirname, TEST_LINK);
+	snprintf(test_file_path, sizeof(test_file_path), "%s/%s", dirname, TEST_FILE);
+
+	if (chdir(dirname)) {
+		err("Can't step into %s", dirname);
 		exit(1);
 	}
 
-	wd_deleted = inotify_add_watch(fd, path, IN_ALL_EVENTS);
-	if (wd_deleted < 0) {
-		fail("inotify_add_watch failed");
+	if (open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0644) < 0) {
+		err("inotify_init failed");
 		exit(1);
 	}
 
-	if (unlink(path)) {
-		fail("can't unlink %s\n", path);
+	if (link(TEST_FILE, TEST_LINK)) {
+		err("Can't link %s -> %s", TEST_FILE, TEST_LINK);
+		exit(1);
+	}
+
+	if (chdir("..")) {
+		err("Can't step into %s", "..");
+		exit(1);
+	}
+
+	if (inotify_add_watch(fd, dirname, mask) < 0) {
+		err("inotify_add_watch failed");
+		exit(1);
+	}
+
+	if (inotify_add_watch(fd, test_link_path, mask) < 0) {
+		err("inotify_add_watch failed");
+		exit(1);
+	}
+
+	if (inotify_add_watch(fd, test_file_path, mask) < 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);
+	}
+
+	if (unlink(test_file_path)) {
+		err("can't unlink %s\n", test_file_path);
+		exit(1);
+	}
+
+	close(link_fd);
+
+	emask = 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);
+
+	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


--i0/AhcQY5QxfSsSZ--


More information about the CRIU mailing list