aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namespace.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 1a9232356ef9..d8924bfaa9db 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2513,20 +2513,29 @@ void put_mnt_ns(struct mnt_namespace *ns)
2513{ 2513{
2514 struct vfsmount *root; 2514 struct vfsmount *root;
2515 LIST_HEAD(umount_list); 2515 LIST_HEAD(umount_list);
2516 spinlock_t *lock;
2517 2516
2518 lock = &get_cpu_var(vfsmount_lock); 2517 /*
2519 if (!atomic_dec_and_lock(&ns->count, lock)) { 2518 * We open code this to avoid vfsmount_write_lock() in case of
2520 put_cpu_var(vfsmount_lock); 2519 * ns->count > 1
2520 */
2521 if (atomic_add_unless(&ns->count, -1, 1))
2522 return;
2523
2524 /*
2525 * Do the full locking here as it's likely that ns->count will
2526 * drop to zero and we have to take namespace_sem and all vfs
2527 * mount locks anyway for umount_tree().
2528 */
2529 down_write(&namespace_sem);
2530 vfsmount_write_lock();
2531 if (!atomic_dec_and_test(&ns->count)) {
2532 vfsmount_write_unlock();
2533 up_write(&namespace_sem);
2521 return; 2534 return;
2522 } 2535 }
2523 root = ns->root; 2536 root = ns->root;
2524 ns->root = NULL; 2537 ns->root = NULL;
2525 spin_unlock(lock);
2526 put_cpu_var(vfsmount_lock);
2527 2538
2528 down_write(&namespace_sem);
2529 vfsmount_write_lock();
2530 umount_tree(root, 0, &umount_list); 2539 umount_tree(root, 0, &umount_list);
2531 vfsmount_write_unlock(); 2540 vfsmount_write_unlock();
2532 up_write(&namespace_sem); 2541 up_write(&namespace_sem);