arm: rockchip_defconfig: enable dwc_otg_310 usb driver
[firefly-linux-kernel-4.4.55.git] / fs / pnode.c
index c524fdddc7fb1f601d6d06ddb46d0affcca89c08..cbaa998ad6252ae36ba587bd3856d812bde7dd1f 100644 (file)
@@ -198,7 +198,7 @@ static struct mount *next_group(struct mount *m, struct mount *origin)
 
 /* all accesses are serialized by namespace_sem */
 static struct user_namespace *user_ns;
-static struct mount *last_dest, *last_source, *dest_master;
+static struct mount *last_dest, *first_source, *last_source, *dest_master;
 static struct mountpoint *mp;
 static struct hlist_head *list;
 
@@ -221,20 +221,22 @@ static int propagate_one(struct mount *m)
                type = CL_MAKE_SHARED;
        } else {
                struct mount *n, *p;
+               bool done;
                for (n = m; ; n = p) {
                        p = n->mnt_master;
-                       if (p == dest_master || IS_MNT_MARKED(p)) {
-                               while (last_dest->mnt_master != p) {
-                                       last_source = last_source->mnt_master;
-                                       last_dest = last_source->mnt_parent;
-                               }
-                               if (!peers(n, last_dest)) {
-                                       last_source = last_source->mnt_master;
-                                       last_dest = last_source->mnt_parent;
-                               }
+                       if (p == dest_master || IS_MNT_MARKED(p))
                                break;
-                       }
                }
+               do {
+                       struct mount *parent = last_source->mnt_parent;
+                       if (last_source == first_source)
+                               break;
+                       done = parent->mnt_master == p;
+                       if (done && peers(n, parent))
+                               break;
+                       last_source = last_source->mnt_master;
+               } while (!done);
+
                type = CL_SLAVE;
                /* beginning of peer group among the slaves? */
                if (IS_MNT_SHARED(m))
@@ -286,6 +288,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
         */
        user_ns = current->nsproxy->mnt_ns->user_ns;
        last_dest = dest_mnt;
+       first_source = source_mnt;
        last_source = source_mnt;
        mp = dest_mp;
        list = tree_list;
@@ -455,3 +458,32 @@ int propagate_umount(struct list_head *list)
                __propagate_umount(mnt);
        return 0;
 }
+
+/*
+ *  Iterates over all slaves, and slaves of slaves.
+ */
+static struct mount *next_descendent(struct mount *root, struct mount *cur)
+{
+       if (!IS_MNT_NEW(cur) && !list_empty(&cur->mnt_slave_list))
+               return first_slave(cur);
+       do {
+               if (cur->mnt_slave.next != &cur->mnt_master->mnt_slave_list)
+                       return next_slave(cur);
+               cur = cur->mnt_master;
+       } while (cur != root);
+       return NULL;
+}
+
+void propagate_remount(struct mount *mnt)
+{
+       struct mount *m = mnt;
+       struct super_block *sb = mnt->mnt.mnt_sb;
+
+       if (sb->s_op->copy_mnt_data) {
+               m = next_descendent(mnt, m);
+               while (m) {
+                       sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data);
+                       m = next_descendent(mnt, m);
+               }
+       }
+}