28
28
29
29
extern int __init init_rootfs (void );
30
30
31
- #define CL_EXPIRE 0x01
32
-
33
31
#ifdef CONFIG_SYSFS
34
32
extern int __init sysfs_init (void );
35
33
#else
@@ -145,13 +143,43 @@ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
145
143
old_nd -> dentry -> d_mounted -- ;
146
144
}
147
145
146
+ void mnt_set_mountpoint (struct vfsmount * mnt , struct dentry * dentry ,
147
+ struct vfsmount * child_mnt )
148
+ {
149
+ child_mnt -> mnt_parent = mntget (mnt );
150
+ child_mnt -> mnt_mountpoint = dget (dentry );
151
+ dentry -> d_mounted ++ ;
152
+ }
153
+
148
154
static void attach_mnt (struct vfsmount * mnt , struct nameidata * nd )
149
155
{
150
- mnt -> mnt_parent = mntget ( nd -> mnt );
151
- mnt -> mnt_mountpoint = dget ( nd -> dentry );
152
- list_add ( & mnt -> mnt_hash , mount_hashtable + hash (nd -> mnt , nd -> dentry ));
156
+ mnt_set_mountpoint ( nd -> mnt , nd -> dentry , mnt );
157
+ list_add_tail ( & mnt -> mnt_hash , mount_hashtable +
158
+ hash (nd -> mnt , nd -> dentry ));
153
159
list_add_tail (& mnt -> mnt_child , & nd -> mnt -> mnt_mounts );
154
- nd -> dentry -> d_mounted ++ ;
160
+ }
161
+
162
+ /*
163
+ * the caller must hold vfsmount_lock
164
+ */
165
+ static void commit_tree (struct vfsmount * mnt )
166
+ {
167
+ struct vfsmount * parent = mnt -> mnt_parent ;
168
+ struct vfsmount * m ;
169
+ LIST_HEAD (head );
170
+ struct namespace * n = parent -> mnt_namespace ;
171
+
172
+ BUG_ON (parent == mnt );
173
+
174
+ list_add_tail (& head , & mnt -> mnt_list );
175
+ list_for_each_entry (m , & head , mnt_list )
176
+ m -> mnt_namespace = n ;
177
+ list_splice (& head , n -> list .prev );
178
+
179
+ list_add_tail (& mnt -> mnt_hash , mount_hashtable +
180
+ hash (parent , mnt -> mnt_mountpoint ));
181
+ list_add_tail (& mnt -> mnt_child , & parent -> mnt_mounts );
182
+ touch_namespace (n );
155
183
}
156
184
157
185
static struct vfsmount * next_mnt (struct vfsmount * p , struct vfsmount * root )
@@ -183,7 +211,11 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
183
211
mnt -> mnt_root = dget (root );
184
212
mnt -> mnt_mountpoint = mnt -> mnt_root ;
185
213
mnt -> mnt_parent = mnt ;
186
- mnt -> mnt_namespace = current -> namespace ;
214
+
215
+ if ((flag & CL_PROPAGATION ) || IS_MNT_SHARED (old ))
216
+ list_add (& mnt -> mnt_share , & old -> mnt_share );
217
+ if (flag & CL_MAKE_SHARED )
218
+ set_mnt_shared (mnt );
187
219
188
220
/* stick the duplicate mount on the same expiry list
189
221
* as the original if that was on one */
@@ -379,7 +411,7 @@ int may_umount(struct vfsmount *mnt)
379
411
380
412
EXPORT_SYMBOL (may_umount );
381
413
382
- static void release_mounts (struct list_head * head )
414
+ void release_mounts (struct list_head * head )
383
415
{
384
416
struct vfsmount * mnt ;
385
417
while (!list_empty (head )) {
@@ -401,7 +433,7 @@ static void release_mounts(struct list_head *head)
401
433
}
402
434
}
403
435
404
- static void umount_tree (struct vfsmount * mnt , struct list_head * kill )
436
+ void umount_tree (struct vfsmount * mnt , struct list_head * kill )
405
437
{
406
438
struct vfsmount * p ;
407
439
@@ -581,7 +613,7 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
581
613
}
582
614
}
583
615
584
- static struct vfsmount * copy_tree (struct vfsmount * mnt , struct dentry * dentry ,
616
+ struct vfsmount * copy_tree (struct vfsmount * mnt , struct dentry * dentry ,
585
617
int flag )
586
618
{
587
619
struct vfsmount * res , * p , * q , * r , * s ;
@@ -626,6 +658,67 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
626
658
return NULL ;
627
659
}
628
660
661
+ /*
662
+ * @source_mnt : mount tree to be attached
663
+ * @nd : place the mount tree @source_mnt is attached
664
+ *
665
+ * NOTE: in the table below explains the semantics when a source mount
666
+ * of a given type is attached to a destination mount of a given type.
667
+ * ---------------------------------------------
668
+ * | BIND MOUNT OPERATION |
669
+ * |********************************************
670
+ * | source-->| shared | private |
671
+ * | dest | | |
672
+ * | | | | |
673
+ * | v | | |
674
+ * |********************************************
675
+ * | shared | shared (++) | shared (+) |
676
+ * | | | |
677
+ * |non-shared| shared (+) | private |
678
+ * *********************************************
679
+ * A bind operation clones the source mount and mounts the clone on the
680
+ * destination mount.
681
+ *
682
+ * (++) the cloned mount is propagated to all the mounts in the propagation
683
+ * tree of the destination mount and the cloned mount is added to
684
+ * the peer group of the source mount.
685
+ * (+) the cloned mount is created under the destination mount and is marked
686
+ * as shared. The cloned mount is added to the peer group of the source
687
+ * mount.
688
+ *
689
+ * if the source mount is a tree, the operations explained above is
690
+ * applied to each mount in the tree.
691
+ * Must be called without spinlocks held, since this function can sleep
692
+ * in allocations.
693
+ */
694
+ static int attach_recursive_mnt (struct vfsmount * source_mnt ,
695
+ struct nameidata * nd )
696
+ {
697
+ LIST_HEAD (tree_list );
698
+ struct vfsmount * dest_mnt = nd -> mnt ;
699
+ struct dentry * dest_dentry = nd -> dentry ;
700
+ struct vfsmount * child , * p ;
701
+
702
+ if (propagate_mnt (dest_mnt , dest_dentry , source_mnt , & tree_list ))
703
+ return - EINVAL ;
704
+
705
+ if (IS_MNT_SHARED (dest_mnt )) {
706
+ for (p = source_mnt ; p ; p = next_mnt (p , source_mnt ))
707
+ set_mnt_shared (p );
708
+ }
709
+
710
+ spin_lock (& vfsmount_lock );
711
+ mnt_set_mountpoint (dest_mnt , dest_dentry , source_mnt );
712
+ commit_tree (source_mnt );
713
+
714
+ list_for_each_entry_safe (child , p , & tree_list , mnt_hash ) {
715
+ list_del_init (& child -> mnt_hash );
716
+ commit_tree (child );
717
+ }
718
+ spin_unlock (& vfsmount_lock );
719
+ return 0 ;
720
+ }
721
+
629
722
static int graft_tree (struct vfsmount * mnt , struct nameidata * nd )
630
723
{
631
724
int err ;
@@ -646,17 +739,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
646
739
goto out_unlock ;
647
740
648
741
err = - ENOENT ;
649
- spin_lock (& vfsmount_lock );
650
- if (IS_ROOT (nd -> dentry ) || !d_unhashed (nd -> dentry )) {
651
- struct list_head head ;
652
-
653
- attach_mnt (mnt , nd );
654
- list_add_tail (& head , & mnt -> mnt_list );
655
- list_splice (& head , current -> namespace -> list .prev );
656
- err = 0 ;
657
- touch_namespace (current -> namespace );
658
- }
659
- spin_unlock (& vfsmount_lock );
742
+ if (IS_ROOT (nd -> dentry ) || !d_unhashed (nd -> dentry ))
743
+ err = attach_recursive_mnt (mnt , nd );
660
744
out_unlock :
661
745
up (& nd -> dentry -> d_inode -> i_sem );
662
746
if (!err )
0 commit comments