@@ -69,6 +69,8 @@ static struct hlist_head *mount_hashtable __read_mostly;
69
69
static struct hlist_head * mountpoint_hashtable __read_mostly ;
70
70
static struct kmem_cache * mnt_cache __read_mostly ;
71
71
static DECLARE_RWSEM (namespace_sem );
72
+ static HLIST_HEAD (unmounted ); /* protected by namespace_sem */
73
+ static LIST_HEAD (ex_mountpoints ); /* protected by namespace_sem */
72
74
73
75
/* /sys/fs */
74
76
struct kobject * fs_kobj ;
@@ -172,7 +174,6 @@ unsigned int mnt_get_count(struct mount *mnt)
172
174
static void drop_mountpoint (struct fs_pin * p )
173
175
{
174
176
struct mount * m = container_of (p , struct mount , mnt_umount );
175
- dput (m -> mnt_ex_mountpoint );
176
177
pin_remove (p );
177
178
mntput (& m -> mnt );
178
179
}
@@ -739,7 +740,7 @@ static struct mountpoint *get_mountpoint(struct dentry *dentry)
739
740
740
741
/* Add the new mountpoint to the hash table */
741
742
read_seqlock_excl (& mount_lock );
742
- new -> m_dentry = dentry ;
743
+ new -> m_dentry = dget ( dentry ) ;
743
744
new -> m_count = 1 ;
744
745
hlist_add_head (& new -> m_hash , mp_hash (dentry ));
745
746
INIT_HLIST_HEAD (& new -> m_list );
@@ -752,19 +753,30 @@ static struct mountpoint *get_mountpoint(struct dentry *dentry)
752
753
return mp ;
753
754
}
754
755
755
- static void put_mountpoint (struct mountpoint * mp )
756
+ /*
757
+ * vfsmount lock must be held. Additionally, the caller is responsible
758
+ * for serializing calls for given disposal list.
759
+ */
760
+ static void __put_mountpoint (struct mountpoint * mp , struct list_head * list )
756
761
{
757
762
if (!-- mp -> m_count ) {
758
763
struct dentry * dentry = mp -> m_dentry ;
759
764
BUG_ON (!hlist_empty (& mp -> m_list ));
760
765
spin_lock (& dentry -> d_lock );
761
766
dentry -> d_flags &= ~DCACHE_MOUNTED ;
762
767
spin_unlock (& dentry -> d_lock );
768
+ dput_to_list (dentry , list );
763
769
hlist_del (& mp -> m_hash );
764
770
kfree (mp );
765
771
}
766
772
}
767
773
774
+ /* called with namespace_lock and vfsmount lock */
775
+ static void put_mountpoint (struct mountpoint * mp )
776
+ {
777
+ __put_mountpoint (mp , & ex_mountpoints );
778
+ }
779
+
768
780
static inline int check_mnt (struct mount * mnt )
769
781
{
770
782
return mnt -> mnt_ns == current -> nsproxy -> mnt_ns ;
@@ -813,7 +825,7 @@ static struct mountpoint *unhash_mnt(struct mount *mnt)
813
825
*/
814
826
static void detach_mnt (struct mount * mnt , struct path * old_path )
815
827
{
816
- old_path -> dentry = mnt -> mnt_mountpoint ;
828
+ old_path -> dentry = dget ( mnt -> mnt_mountpoint ) ;
817
829
old_path -> mnt = & mnt -> mnt_parent -> mnt ;
818
830
put_mountpoint (unhash_mnt (mnt ));
819
831
}
@@ -823,8 +835,6 @@ static void detach_mnt(struct mount *mnt, struct path *old_path)
823
835
*/
824
836
static void umount_mnt (struct mount * mnt )
825
837
{
826
- /* old mountpoint will be dropped when we can do that */
827
- mnt -> mnt_ex_mountpoint = mnt -> mnt_mountpoint ;
828
838
put_mountpoint (unhash_mnt (mnt ));
829
839
}
830
840
@@ -837,7 +847,7 @@ void mnt_set_mountpoint(struct mount *mnt,
837
847
{
838
848
mp -> m_count ++ ;
839
849
mnt_add_count (mnt , 1 ); /* essentially, that's mntget */
840
- child_mnt -> mnt_mountpoint = dget ( mp -> m_dentry ) ;
850
+ child_mnt -> mnt_mountpoint = mp -> m_dentry ;
841
851
child_mnt -> mnt_parent = mnt ;
842
852
child_mnt -> mnt_mp = mp ;
843
853
hlist_add_head (& child_mnt -> mnt_mp_list , & mp -> m_list );
@@ -864,7 +874,6 @@ static void attach_mnt(struct mount *mnt,
864
874
void mnt_change_mountpoint (struct mount * parent , struct mountpoint * mp , struct mount * mnt )
865
875
{
866
876
struct mountpoint * old_mp = mnt -> mnt_mp ;
867
- struct dentry * old_mountpoint = mnt -> mnt_mountpoint ;
868
877
struct mount * old_parent = mnt -> mnt_parent ;
869
878
870
879
list_del_init (& mnt -> mnt_child );
@@ -874,22 +883,6 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct m
874
883
attach_mnt (mnt , parent , mp );
875
884
876
885
put_mountpoint (old_mp );
877
-
878
- /*
879
- * Safely avoid even the suggestion this code might sleep or
880
- * lock the mount hash by taking advantage of the knowledge that
881
- * mnt_change_mountpoint will not release the final reference
882
- * to a mountpoint.
883
- *
884
- * During mounting, the mount passed in as the parent mount will
885
- * continue to use the old mountpoint and during unmounting, the
886
- * old mountpoint will continue to exist until namespace_unlock,
887
- * which happens well after mnt_change_mountpoint.
888
- */
889
- spin_lock (& old_mountpoint -> d_lock );
890
- old_mountpoint -> d_lockref .count -- ;
891
- spin_unlock (& old_mountpoint -> d_lock );
892
-
893
886
mnt_add_count (old_parent , -1 );
894
887
}
895
888
@@ -1142,6 +1135,8 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
1142
1135
1143
1136
static void mntput_no_expire (struct mount * mnt )
1144
1137
{
1138
+ LIST_HEAD (list );
1139
+
1145
1140
rcu_read_lock ();
1146
1141
if (likely (READ_ONCE (mnt -> mnt_ns ))) {
1147
1142
/*
@@ -1182,10 +1177,11 @@ static void mntput_no_expire(struct mount *mnt)
1182
1177
if (unlikely (!list_empty (& mnt -> mnt_mounts ))) {
1183
1178
struct mount * p , * tmp ;
1184
1179
list_for_each_entry_safe (p , tmp , & mnt -> mnt_mounts , mnt_child ) {
1185
- umount_mnt ( p );
1180
+ __put_mountpoint ( unhash_mnt ( p ), & list );
1186
1181
}
1187
1182
}
1188
1183
unlock_mount_hash ();
1184
+ shrink_dentry_list (& list );
1189
1185
1190
1186
if (likely (!(mnt -> mnt .mnt_flags & MNT_INTERNAL ))) {
1191
1187
struct task_struct * task = current ;
@@ -1371,16 +1367,18 @@ int may_umount(struct vfsmount *mnt)
1371
1367
1372
1368
EXPORT_SYMBOL (may_umount );
1373
1369
1374
- static HLIST_HEAD (unmounted ); /* protected by namespace_sem */
1375
-
1376
1370
static void namespace_unlock (void )
1377
1371
{
1378
1372
struct hlist_head head ;
1373
+ LIST_HEAD (list );
1379
1374
1380
1375
hlist_move_list (& unmounted , & head );
1376
+ list_splice_init (& ex_mountpoints , & list );
1381
1377
1382
1378
up_write (& namespace_sem );
1383
1379
1380
+ shrink_dentry_list (& list );
1381
+
1384
1382
if (likely (hlist_empty (& head )))
1385
1383
return ;
1386
1384
0 commit comments