[CRIU] [PATCH 7/9] mounts: if a mount can't be mounted, it is queued in postpone list

Andrey Vagin avagin at openvz.org
Tue Jul 9 07:05:54 EDT 2013


Try to restore mounts while a postpone list isn't empty and check
that each iteration has some progress, otherwice it will fails for
preventing infinite loops

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/proc_parse.h |  2 ++
 mount.c              | 40 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/include/proc_parse.h b/include/proc_parse.h
index 1325424..85bde36 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -123,6 +123,8 @@ struct mount_info {
 	struct list_head mnt_slave_list;/* list of slave mounts */
 	struct list_head mnt_slave;	/* slave list entry */
 	struct mount_info *mnt_master;	/* slave is on master->mnt_slave_list */
+
+	struct list_head postpone;
 };
 
 struct proc_posix_timer {
diff --git a/mount.c b/mount.c
index 0609ded..fae9513 100644
--- a/mount.c
+++ b/mount.c
@@ -533,12 +533,25 @@ int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset)
 	return 0;
 }
 
-#define MNT_TREE_WALK(_r, _el, _fn_f, _fn_r) do {				\
+static int mount_progress;
+
+#define MNT_TREE_WALK(_r, _el, _fn_f, _fn_r, _plist) do {			\
 		struct mount_info *_mi = _r;					\
 										\
 		while (1) {							\
-			if (_fn_f(_mi))						\
+			int ret;						\
+										\
+			ret = _fn_f(_mi);					\
+			if (ret < 0)						\
 				return -1;					\
+			else if (ret > 0) {					\
+				list_add_tail(&_mi->postpone, _plist);		\
+				goto up;					\
+			}							\
+										\
+			list_del(&_mi->postpone);				\
+			mount_progress++;					\
+										\
 			if (!list_empty(&_mi->children)) {			\
 				_mi = list_entry(_mi->children._el,		\
 						struct mount_info, siblings);	\
@@ -564,13 +577,32 @@ int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset)
 static int mnt_tree_for_each(struct mount_info *m,
 		int (*fn)(struct mount_info *))
 {
-	MNT_TREE_WALK(m, next, fn, MNT_WALK_NONE);
+	static LIST_HEAD(postpone);
+
+	list_add(&m->postpone, &postpone);
+
+	while (!list_empty(&postpone)) {
+		int old = mount_progress;
+		list_for_each_entry(m, &postpone, postpone)
+			MNT_TREE_WALK(m, next, fn, MNT_WALK_NONE, &postpone);
+		if (old == mount_progress) {
+			pr_err("A few mount points can't be mounted");
+			list_for_each_entry(m, &postpone, postpone) {
+				pr_err("%d:%d %s %s %s\n", m->mnt_id,
+					m->parent_mnt_id, m->root,
+					m->mountpoint, m->source);
+			}
+			return -1;
+		}
+	}
+
+	return 0;
 }
 
 static int mnt_tree_for_each_reverse(struct mount_info *m,
 		int (*fn)(struct mount_info *))
 {
-	MNT_TREE_WALK(m, prev, MNT_WALK_NONE, fn);
+	MNT_TREE_WALK(m, prev, MNT_WALK_NONE, fn, (struct list_head *) NULL);
 }
 
 static char *resolve_source(struct mount_info *mi)
-- 
1.8.3.1



More information about the CRIU mailing list