@@ -2310,21 +2310,62 @@ struct mount *copy_tree(struct mount *src_root, struct dentry *dentry,
23102310 return dst_mnt ;
23112311}
23122312
2313- /* Caller should check returned pointer for errors */
2313+ static inline bool extend_array (struct path * * res , struct path * * to_free ,
2314+ unsigned n , unsigned * count , unsigned new_count )
2315+ {
2316+ struct path * p ;
23142317
2315- struct vfsmount * collect_mounts (const struct path * path )
2318+ if (likely (n < * count ))
2319+ return true;
2320+ p = kmalloc_array (new_count , sizeof (struct path ), GFP_KERNEL );
2321+ if (p && * count )
2322+ memcpy (p , * res , * count * sizeof (struct path ));
2323+ * count = new_count ;
2324+ kfree (* to_free );
2325+ * to_free = * res = p ;
2326+ return p ;
2327+ }
2328+
2329+ struct path * collect_paths (const struct path * path ,
2330+ struct path * prealloc , unsigned count )
23162331{
2317- struct mount * tree ;
2318- namespace_lock ();
2319- if (!check_mnt (real_mount (path -> mnt )))
2320- tree = ERR_PTR (- EINVAL );
2321- else
2322- tree = copy_tree (real_mount (path -> mnt ), path -> dentry ,
2323- CL_COPY_ALL | CL_PRIVATE );
2324- namespace_unlock ();
2325- if (IS_ERR (tree ))
2326- return ERR_CAST (tree );
2327- return & tree -> mnt ;
2332+ struct mount * root = real_mount (path -> mnt );
2333+ struct mount * child ;
2334+ struct path * res = prealloc , * to_free = NULL ;
2335+ unsigned n = 0 ;
2336+
2337+ guard (rwsem_read )(& namespace_sem );
2338+
2339+ if (!check_mnt (root ))
2340+ return ERR_PTR (- EINVAL );
2341+ if (!extend_array (& res , & to_free , 0 , & count , 32 ))
2342+ return ERR_PTR (- ENOMEM );
2343+ res [n ++ ] = * path ;
2344+ list_for_each_entry (child , & root -> mnt_mounts , mnt_child ) {
2345+ if (!is_subdir (child -> mnt_mountpoint , path -> dentry ))
2346+ continue ;
2347+ for (struct mount * m = child ; m ; m = next_mnt (m , child )) {
2348+ if (!extend_array (& res , & to_free , n , & count , 2 * count ))
2349+ return ERR_PTR (- ENOMEM );
2350+ res [n ].mnt = & m -> mnt ;
2351+ res [n ].dentry = m -> mnt .mnt_root ;
2352+ n ++ ;
2353+ }
2354+ }
2355+ if (!extend_array (& res , & to_free , n , & count , count + 1 ))
2356+ return ERR_PTR (- ENOMEM );
2357+ memset (res + n , 0 , (count - n ) * sizeof (struct path ));
2358+ for (struct path * p = res ; p -> mnt ; p ++ )
2359+ path_get (p );
2360+ return res ;
2361+ }
2362+
2363+ void drop_collected_paths (struct path * paths , struct path * prealloc )
2364+ {
2365+ for (struct path * p = paths ; p -> mnt ; p ++ )
2366+ path_put (p );
2367+ if (paths != prealloc )
2368+ kfree (paths );
23282369}
23292370
23302371static void free_mnt_ns (struct mnt_namespace * );
@@ -2401,15 +2442,6 @@ void dissolve_on_fput(struct vfsmount *mnt)
24012442 free_mnt_ns (ns );
24022443}
24032444
2404- void drop_collected_mounts (struct vfsmount * mnt )
2405- {
2406- namespace_lock ();
2407- lock_mount_hash ();
2408- umount_tree (real_mount (mnt ), 0 );
2409- unlock_mount_hash ();
2410- namespace_unlock ();
2411- }
2412-
24132445static bool __has_locked_children (struct mount * mnt , struct dentry * dentry )
24142446{
24152447 struct mount * child ;
@@ -2511,21 +2543,6 @@ struct vfsmount *clone_private_mount(const struct path *path)
25112543}
25122544EXPORT_SYMBOL_GPL (clone_private_mount );
25132545
2514- int iterate_mounts (int (* f )(struct vfsmount * , void * ), void * arg ,
2515- struct vfsmount * root )
2516- {
2517- struct mount * mnt ;
2518- int res = f (root , arg );
2519- if (res )
2520- return res ;
2521- list_for_each_entry (mnt , & real_mount (root )-> mnt_list , mnt_list ) {
2522- res = f (& mnt -> mnt , arg );
2523- if (res )
2524- return res ;
2525- }
2526- return 0 ;
2527- }
2528-
25292546static void lock_mnt_tree (struct mount * mnt )
25302547{
25312548 struct mount * p ;
@@ -2751,14 +2768,14 @@ static int attach_recursive_mnt(struct mount *source_mnt,
27512768 hlist_for_each_entry_safe (child , n , & tree_list , mnt_hash ) {
27522769 struct mount * q ;
27532770 hlist_del_init (& child -> mnt_hash );
2754- q = __lookup_mnt (& child -> mnt_parent -> mnt ,
2755- child -> mnt_mountpoint );
2756- if (q )
2757- mnt_change_mountpoint (child , smp , q );
27582771 /* Notice when we are propagating across user namespaces */
27592772 if (child -> mnt_parent -> mnt_ns -> user_ns != user_ns )
27602773 lock_mnt_tree (child );
27612774 child -> mnt .mnt_flags &= ~MNT_LOCKED ;
2775+ q = __lookup_mnt (& child -> mnt_parent -> mnt ,
2776+ child -> mnt_mountpoint );
2777+ if (q )
2778+ mnt_change_mountpoint (child , smp , q );
27622779 commit_tree (child );
27632780 }
27642781 put_mountpoint (smp );
@@ -5290,16 +5307,12 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename,
52905307 kattr .kflags |= MOUNT_KATTR_RECURSE ;
52915308
52925309 ret = wants_mount_setattr (uattr , usize , & kattr );
5293- if (ret < 0 )
5294- return ret ;
5295-
5296- if (ret ) {
5310+ if (ret > 0 ) {
52975311 ret = do_mount_setattr (& file -> f_path , & kattr );
5298- if (ret )
5299- return ret ;
5300-
53015312 finish_mount_kattr (& kattr );
53025313 }
5314+ if (ret )
5315+ return ret ;
53035316 }
53045317
53055318 fd = get_unused_fd_flags (flags & O_CLOEXEC );
@@ -6262,7 +6275,11 @@ void put_mnt_ns(struct mnt_namespace *ns)
62626275{
62636276 if (!refcount_dec_and_test (& ns -> ns .count ))
62646277 return ;
6265- drop_collected_mounts (& ns -> root -> mnt );
6278+ namespace_lock ();
6279+ lock_mount_hash ();
6280+ umount_tree (ns -> root , 0 );
6281+ unlock_mount_hash ();
6282+ namespace_unlock ();
62666283 free_mnt_ns (ns );
62676284}
62686285
0 commit comments