@@ -81,6 +81,9 @@ static HLIST_HEAD(unmounted); /* protected by namespace_sem */
8181static LIST_HEAD (ex_mountpoints ); /* protected by namespace_sem */
8282static DEFINE_SEQLOCK (mnt_ns_tree_lock );
8383
84+ #ifdef CONFIG_FSNOTIFY
85+ LIST_HEAD (notify_list ); /* protected by namespace_sem */
86+ #endif
8487static struct rb_root mnt_ns_tree = RB_ROOT ; /* protected by mnt_ns_tree_lock */
8588static LIST_HEAD (mnt_ns_list ); /* protected by mnt_ns_tree_lock */
8689
@@ -163,6 +166,7 @@ static void mnt_ns_release(struct mnt_namespace *ns)
163166{
164167 /* keep alive for {list,stat}mount() */
165168 if (refcount_dec_and_test (& ns -> passive )) {
169+ fsnotify_mntns_delete (ns );
166170 put_user_ns (ns -> user_ns );
167171 kfree (ns );
168172 }
@@ -1176,6 +1180,8 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
11761180 ns -> mnt_first_node = & mnt -> mnt_node ;
11771181 rb_link_node (& mnt -> mnt_node , parent , link );
11781182 rb_insert_color (& mnt -> mnt_node , & ns -> mounts );
1183+
1184+ mnt_notify_add (mnt );
11791185}
11801186
11811187/*
@@ -1723,6 +1729,50 @@ int may_umount(struct vfsmount *mnt)
17231729
17241730EXPORT_SYMBOL (may_umount );
17251731
1732+ #ifdef CONFIG_FSNOTIFY
1733+ static void mnt_notify (struct mount * p )
1734+ {
1735+ if (!p -> prev_ns && p -> mnt_ns ) {
1736+ fsnotify_mnt_attach (p -> mnt_ns , & p -> mnt );
1737+ } else if (p -> prev_ns && !p -> mnt_ns ) {
1738+ fsnotify_mnt_detach (p -> prev_ns , & p -> mnt );
1739+ } else if (p -> prev_ns == p -> mnt_ns ) {
1740+ fsnotify_mnt_move (p -> mnt_ns , & p -> mnt );
1741+ } else {
1742+ fsnotify_mnt_detach (p -> prev_ns , & p -> mnt );
1743+ fsnotify_mnt_attach (p -> mnt_ns , & p -> mnt );
1744+ }
1745+ p -> prev_ns = p -> mnt_ns ;
1746+ }
1747+
1748+ static void notify_mnt_list (void )
1749+ {
1750+ struct mount * m , * tmp ;
1751+ /*
1752+ * Notify about mounts that were added/reparented/detached/remain
1753+ * connected after unmount.
1754+ */
1755+ list_for_each_entry_safe (m , tmp , & notify_list , to_notify ) {
1756+ mnt_notify (m );
1757+ list_del_init (& m -> to_notify );
1758+ }
1759+ }
1760+
1761+ static bool need_notify_mnt_list (void )
1762+ {
1763+ return !list_empty (& notify_list );
1764+ }
1765+ #else
1766+ static void notify_mnt_list (void )
1767+ {
1768+ }
1769+
1770+ static bool need_notify_mnt_list (void )
1771+ {
1772+ return false;
1773+ }
1774+ #endif
1775+
17261776static void namespace_unlock (void )
17271777{
17281778 struct hlist_head head ;
@@ -1733,7 +1783,18 @@ static void namespace_unlock(void)
17331783 hlist_move_list (& unmounted , & head );
17341784 list_splice_init (& ex_mountpoints , & list );
17351785
1736- up_write (& namespace_sem );
1786+ if (need_notify_mnt_list ()) {
1787+ /*
1788+ * No point blocking out concurrent readers while notifications
1789+ * are sent. This will also allow statmount()/listmount() to run
1790+ * concurrently.
1791+ */
1792+ downgrade_write (& namespace_sem );
1793+ notify_mnt_list ();
1794+ up_read (& namespace_sem );
1795+ } else {
1796+ up_write (& namespace_sem );
1797+ }
17371798
17381799 shrink_dentry_list (& list );
17391800
@@ -1846,6 +1907,19 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
18461907 change_mnt_propagation (p , MS_PRIVATE );
18471908 if (disconnect )
18481909 hlist_add_head (& p -> mnt_umount , & unmounted );
1910+
1911+ /*
1912+ * At this point p->mnt_ns is NULL, notification will be queued
1913+ * only if
1914+ *
1915+ * - p->prev_ns is non-NULL *and*
1916+ * - p->prev_ns->n_fsnotify_marks is non-NULL
1917+ *
1918+ * This will preclude queuing the mount if this is a cleanup
1919+ * after a failed copy_tree() or destruction of an anonymous
1920+ * namespace, etc.
1921+ */
1922+ mnt_notify_add (p );
18491923 }
18501924}
18511925
@@ -2555,6 +2629,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
25552629 dest_mp = smp ;
25562630 unhash_mnt (source_mnt );
25572631 attach_mnt (source_mnt , top_mnt , dest_mp , beneath );
2632+ mnt_notify_add (source_mnt );
25582633 touch_mnt_namespace (source_mnt -> mnt_ns );
25592634 } else {
25602635 if (source_mnt -> mnt_ns ) {
@@ -4476,6 +4551,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
44764551 list_del_init (& new_mnt -> mnt_expire );
44774552 put_mountpoint (root_mp );
44784553 unlock_mount_hash ();
4554+ mnt_notify_add (root_mnt );
4555+ mnt_notify_add (new_mnt );
44794556 chroot_fs_refs (& root , & new );
44804557 error = 0 ;
44814558out4 :
0 commit comments