[CRIU] [PATCH 1/3] fsnotify: merge inotify wd image into inotify image (v4)

Andrey Vagin avagin at openvz.org
Tue Sep 2 07:49:30 PDT 2014


All watch descriptors are collected in a list and then
they are written in inotify image as a repeated field.

This images merge reduces the amount of image files criu
generates and may simplify the fix of mentioned above issue.

v2: use free_inotify_wd_entry() instead of xfree in dump_one_inotify()
v3: don't leak ie.wd_entry
v4: save the original order of watchers
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 fsnotify.c              | 85 +++++++++++++++++++++++++++++++++++++++----------
 include/image-desc.h    |  2 +-
 protobuf/fsnotify.proto |  1 +
 3 files changed, 70 insertions(+), 18 deletions(-)

diff --git a/fsnotify.c b/fsnotify.c
index c9373c7..dff548c 100644
--- a/fsnotify.c
+++ b/fsnotify.c
@@ -197,40 +197,68 @@ err:
 	return -1;
 }
 
+struct watch_list {
+	struct list_head list;
+	int n;
+};
+
 static int dump_inotify_entry(union fdinfo_entries *e, void *arg)
 {
-	InotifyWdEntry *we = &e->ify.e;
-	int ret = -1;
+	struct watch_list *wd_list = (struct watch_list *) arg;
+	struct inotify_wd_entry *wd_entry = (struct inotify_wd_entry *) e;;
+	InotifyWdEntry *we = &wd_entry->e;
 
-	we->id = *(u32 *)arg;
 	pr_info("wd: wd 0x%08x s_dev 0x%08x i_ino 0x%16"PRIx64" mask 0x%08x\n",
 			we->wd, we->s_dev, we->i_ino, we->mask);
 	pr_info("\t[fhandle] bytes 0x%08x type 0x%08x __handle 0x%016"PRIx64":0x%016"PRIx64"\n",
 			we->f_handle->bytes, we->f_handle->type,
 			we->f_handle->handle[0], we->f_handle->handle[1]);
 
-	if (check_open_handle(we->s_dev, we->i_ino, we->f_handle))
-		goto out;
+	if (check_open_handle(we->s_dev, we->i_ino, we->f_handle)) {
+		free_inotify_wd_entry(e);
+		return -1;
+	}
 
-	ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_INOTIFY_WD), we, PB_INOTIFY_WD);
-out:
-	free_inotify_wd_entry(e);
-	return ret;
+	list_add_tail(&wd_entry->node, &wd_list->list);
+	wd_list->n++;
+
+	return 0;
 }
 
 static int dump_one_inotify(int lfd, u32 id, const struct fd_parms *p)
 {
+	struct watch_list wd_list = {LIST_HEAD_INIT(wd_list.list), 0};
 	InotifyFileEntry ie = INOTIFY_FILE_ENTRY__INIT;
+	union fdinfo_entries *we, *tmp;
+	int exit_code = -1, i;
 
 	ie.id = id;
 	ie.flags = p->flags;
 	ie.fown = (FownEntry *)&p->fown;
 
+	if (parse_fdinfo(lfd, FD_TYPES__INOTIFY, dump_inotify_entry, &wd_list))
+		goto free;
+
+	ie.wd = xmalloc(sizeof(*ie.wd) * wd_list.n);
+	if (!ie.wd)
+		goto free;
+
+	i = 0;
+	list_for_each_entry(we, &wd_list.list, ify.node)
+		ie.wd[i++] = &we->ify.e;
+	ie.n_wd = wd_list.n;
+
 	pr_info("id 0x%08x flags 0x%08x\n", ie.id, ie.flags);
 	if (pb_write_one(fdset_fd(glob_fdset, CR_FD_INOTIFY_FILE), &ie, PB_INOTIFY_FILE))
-		return -1;
+		goto free;
 
-	return parse_fdinfo(lfd, FD_TYPES__INOTIFY, dump_inotify_entry, &id);
+	exit_code = 0;
+free:
+	xfree(ie.wd);
+	list_for_each_entry_safe(we, tmp, &wd_list.list, ify.node)
+		free_inotify_wd_entry(we);
+
+	return exit_code;
 }
 
 static int pre_dump_inotify_entry(union fdinfo_entries *e, void *arg)
@@ -613,15 +641,10 @@ static struct fsnotify_file_info *find_inotify_info(unsigned id)
 	return NULL;
 }
 
-static int collect_inotify_mark(struct fsnotify_mark_info *mark)
+static int __collect_inotify_mark(struct fsnotify_file_info *p, struct fsnotify_mark_info *mark)
 {
-	struct fsnotify_file_info *p;
 	struct fsnotify_mark_info *m;
 
-	p = find_inotify_info(mark->iwe->id);
-	if (!p)
-		return -1;
-
 	/*
 	 * We should put marks in wd ascending order. See comment
 	 * in restore_one_inotify() for explanation.
@@ -635,6 +658,17 @@ static int collect_inotify_mark(struct fsnotify_mark_info *mark)
 	return 0;
 }
 
+static int collect_inotify_mark(struct fsnotify_mark_info *mark)
+{
+	struct fsnotify_file_info *p;
+
+	p = find_inotify_info(mark->iwe->id);
+	if (!p)
+		return -1;
+
+	return __collect_inotify_mark(p, mark);
+}
+
 static int collect_fanotify_mark(struct fsnotify_mark_info *mark)
 {
 	struct fsnotify_file_info *p;
@@ -656,11 +690,28 @@ static int collect_fanotify_mark(struct fsnotify_mark_info *mark)
 static int collect_one_inotify(void *o, ProtobufCMessage *msg)
 {
 	struct fsnotify_file_info *info = o;
+	int i;
 
 	info->ife = pb_msg(msg, InotifyFileEntry);
 	INIT_LIST_HEAD(&info->marks);
 	list_add(&info->list, &inotify_info_head);
 	pr_info("Collected id 0x%08x flags 0x%08x\n", info->ife->id, info->ife->flags);
+
+	for (i = 0; i < info->ife->n_wd; i++) {
+		struct fsnotify_mark_info *mark;
+
+		mark = xmalloc(sizeof(*mark));
+		if (!mark)
+			return -1;
+
+		mark->iwe = info->ife->wd[i];
+		INIT_LIST_HEAD(&mark->list);
+		mark->remap = NULL;
+
+		if (__collect_inotify_mark(info, mark))
+			return -1;
+	}
+
 	return file_desc_add(&info->d, info->ife->id, &inotify_desc_ops);
 }
 
diff --git a/include/image-desc.h b/include/image-desc.h
index ab592a1..75e851c 100644
--- a/include/image-desc.h
+++ b/include/image-desc.h
@@ -68,7 +68,6 @@ enum {
 	CR_FD_EVENTPOLL_TFD,
 	CR_FD_SIGNALFD,
 	CR_FD_INOTIFY_FILE,
-	CR_FD_INOTIFY_WD,
 	CR_FD_FANOTIFY_FILE,
 	CR_FD_FANOTIFY_MARK,
 	CR_FD_TUNFILE,
@@ -93,6 +92,7 @@ enum {
 
 	CR_FD_SIGNAL,
 	CR_FD_PSIGNAL,
+	CR_FD_INOTIFY_WD,
 
 	CR_FD_MAX
 };
diff --git a/protobuf/fsnotify.proto b/protobuf/fsnotify.proto
index 073fa79..b3fc080 100644
--- a/protobuf/fsnotify.proto
+++ b/protobuf/fsnotify.proto
@@ -15,6 +15,7 @@ message inotify_file_entry {
 	required uint32		id		= 1;
 	required uint32		flags		= 2;
 	required fown_entry	fown		= 4;
+	repeated inotify_wd_entry wd		= 5;
 }
 
 enum mark_type {
-- 
1.9.3



More information about the CRIU mailing list