aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-01-10 19:01:08 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-25 23:17:29 -0500
commit87b95ce0964c016ede92763be9c164e49f1019e9 (patch)
tree168ea89fd898a2a0c70601d252171fc1a76f15f9 /fs/namespace.c
parent59eda0e07f43c950d31756213b607af673e551f0 (diff)
switch the IO-triggering parts of umount to fs_pin
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c44
1 files changed, 17 insertions, 27 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index cd1e9681a0cf..4a985ff0ddfc 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -190,6 +190,14 @@ unsigned int mnt_get_count(struct mount *mnt)
190#endif 190#endif
191} 191}
192 192
193static void drop_mountpoint(struct fs_pin *p)
194{
195 struct mount *m = container_of(p, struct mount, mnt_umount);
196 dput(m->mnt_ex_mountpoint);
197 pin_remove(p);
198 mntput(&m->mnt);
199}
200
193static struct mount *alloc_vfsmnt(const char *name) 201static struct mount *alloc_vfsmnt(const char *name)
194{ 202{
195 struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); 203 struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
@@ -229,6 +237,7 @@ static struct mount *alloc_vfsmnt(const char *name)
229#ifdef CONFIG_FSNOTIFY 237#ifdef CONFIG_FSNOTIFY
230 INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); 238 INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
231#endif 239#endif
240 init_fs_pin(&mnt->mnt_umount, drop_mountpoint);
232 } 241 }
233 return mnt; 242 return mnt;
234 243
@@ -1289,7 +1298,6 @@ static HLIST_HEAD(unmounted); /* protected by namespace_sem */
1289 1298
1290static void namespace_unlock(void) 1299static void namespace_unlock(void)
1291{ 1300{
1292 struct mount *mnt;
1293 struct hlist_head head = unmounted; 1301 struct hlist_head head = unmounted;
1294 1302
1295 if (likely(hlist_empty(&head))) { 1303 if (likely(hlist_empty(&head))) {
@@ -1299,23 +1307,11 @@ static void namespace_unlock(void)
1299 1307
1300 head.first->pprev = &head.first; 1308 head.first->pprev = &head.first;
1301 INIT_HLIST_HEAD(&unmounted); 1309 INIT_HLIST_HEAD(&unmounted);
1302
1303 /* undo decrements we'd done in umount_tree() */
1304 hlist_for_each_entry(mnt, &head, mnt_hash)
1305 if (mnt->mnt_ex_mountpoint.mnt)
1306 mntget(mnt->mnt_ex_mountpoint.mnt);
1307
1308 up_write(&namespace_sem); 1310 up_write(&namespace_sem);
1309 1311
1310 synchronize_rcu(); 1312 synchronize_rcu();
1311 1313
1312 while (!hlist_empty(&head)) { 1314 group_pin_kill(&head);
1313 mnt = hlist_entry(head.first, struct mount, mnt_hash);
1314 hlist_del_init(&mnt->mnt_hash);
1315 if (mnt->mnt_ex_mountpoint.mnt)
1316 path_put(&mnt->mnt_ex_mountpoint);
1317 mntput(&mnt->mnt);
1318 }
1319} 1315}
1320 1316
1321static inline void namespace_lock(void) 1317static inline void namespace_lock(void)
@@ -1334,7 +1330,6 @@ void umount_tree(struct mount *mnt, int how)
1334{ 1330{
1335 HLIST_HEAD(tmp_list); 1331 HLIST_HEAD(tmp_list);
1336 struct mount *p; 1332 struct mount *p;
1337 struct mount *last = NULL;
1338 1333
1339 for (p = mnt; p; p = next_mnt(p, mnt)) { 1334 for (p = mnt; p; p = next_mnt(p, mnt)) {
1340 hlist_del_init_rcu(&p->mnt_hash); 1335 hlist_del_init_rcu(&p->mnt_hash);
@@ -1347,33 +1342,28 @@ void umount_tree(struct mount *mnt, int how)
1347 if (how) 1342 if (how)
1348 propagate_umount(&tmp_list); 1343 propagate_umount(&tmp_list);
1349 1344
1350 hlist_for_each_entry(p, &tmp_list, mnt_hash) { 1345 while (!hlist_empty(&tmp_list)) {
1346 p = hlist_entry(tmp_list.first, struct mount, mnt_hash);
1347 hlist_del_init_rcu(&p->mnt_hash);
1351 list_del_init(&p->mnt_expire); 1348 list_del_init(&p->mnt_expire);
1352 list_del_init(&p->mnt_list); 1349 list_del_init(&p->mnt_list);
1353 __touch_mnt_namespace(p->mnt_ns); 1350 __touch_mnt_namespace(p->mnt_ns);
1354 p->mnt_ns = NULL; 1351 p->mnt_ns = NULL;
1355 if (how < 2) 1352 if (how < 2)
1356 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; 1353 p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
1354
1355 pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted);
1357 if (mnt_has_parent(p)) { 1356 if (mnt_has_parent(p)) {
1358 hlist_del_init(&p->mnt_mp_list); 1357 hlist_del_init(&p->mnt_mp_list);
1359 put_mountpoint(p->mnt_mp); 1358 put_mountpoint(p->mnt_mp);
1360 mnt_add_count(p->mnt_parent, -1); 1359 mnt_add_count(p->mnt_parent, -1);
1361 /* move the reference to mountpoint into ->mnt_ex_mountpoint */ 1360 /* old mountpoint will be dropped when we can do that */
1362 p->mnt_ex_mountpoint.dentry = p->mnt_mountpoint; 1361 p->mnt_ex_mountpoint = p->mnt_mountpoint;
1363 p->mnt_ex_mountpoint.mnt = &p->mnt_parent->mnt;
1364 p->mnt_mountpoint = p->mnt.mnt_root; 1362 p->mnt_mountpoint = p->mnt.mnt_root;
1365 p->mnt_parent = p; 1363 p->mnt_parent = p;
1366 p->mnt_mp = NULL; 1364 p->mnt_mp = NULL;
1367 } 1365 }
1368 change_mnt_propagation(p, MS_PRIVATE); 1366 change_mnt_propagation(p, MS_PRIVATE);
1369 last = p;
1370 }
1371 if (last) {
1372 last->mnt_hash.next = unmounted.first;
1373 if (unmounted.first)
1374 unmounted.first->pprev = &last->mnt_hash.next;
1375 unmounted.first = tmp_list.first;
1376 unmounted.first->pprev = &unmounted.first;
1377 } 1367 }
1378} 1368}
1379 1369