]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/namespace.c
Merge remote-tracking branch 'userns/for-next'
[karo-tx-linux.git] / fs / namespace.c
index e4fe22c23e00d1e182246732530bce4b33174262..ca81c46ea649831ea3767ba114ba9a5c360df1a9 100644 (file)
@@ -39,7 +39,7 @@ static int mnt_group_start = 1;
 static struct list_head *mount_hashtable __read_mostly;
 static struct list_head *mountpoint_hashtable __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+static DECLARE_RWSEM(namespace_sem);
 
 /* /sys/fs */
 struct kobject *fs_kobj;
@@ -1295,6 +1295,30 @@ static int do_umount(struct mount *mnt, int flags)
        return retval;
 }
 
+void detach_mounts(struct dentry *dentry)
+{
+       struct mountpoint *mp;
+       struct mount *mnt;
+
+       namespace_lock();
+       if (!d_mountpoint(dentry))
+               goto out_unlock;
+
+       mp = new_mountpoint(dentry);
+       if (IS_ERR(mp))
+               goto out_unlock;
+
+       br_write_lock(&vfsmount_lock);
+       while (!list_empty(&mp->m_list)) {
+               mnt = list_first_entry(&mp->m_list, struct mount, mnt_mp_list);
+               umount_tree(mnt, 1);
+       }
+       br_write_unlock(&vfsmount_lock);
+       put_mountpoint(mp);
+out_unlock:
+       namespace_unlock();
+}
+
 /* 
  * Is the caller allowed to modify his namespace?
  */
@@ -1855,14 +1879,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
                br_write_lock(&vfsmount_lock);
                mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
                mnt->mnt.mnt_flags = mnt_flags;
-               br_write_unlock(&vfsmount_lock);
-       }
-       up_write(&sb->s_umount);
-       if (!err) {
-               br_write_lock(&vfsmount_lock);
                touch_mnt_namespace(mnt->mnt_ns);
                br_write_unlock(&vfsmount_lock);
        }
+       up_write(&sb->s_umount);
        return err;
 }
 
@@ -2450,9 +2470,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
                return ERR_CAST(new);
        }
        new_ns->root = new;
-       br_write_lock(&vfsmount_lock);
        list_add_tail(&new_ns->list, &new->mnt_list);
-       br_write_unlock(&vfsmount_lock);
 
        /*
         * Second pass: switch the tsk->fs->* elements and mark new vfsmounts
@@ -2773,8 +2791,6 @@ void __init mnt_init(void)
        unsigned u;
        int err;
 
-       init_rwsem(&namespace_sem);
-
        mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
                        0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
@@ -2808,11 +2824,7 @@ void put_mnt_ns(struct mnt_namespace *ns)
 {
        if (!atomic_dec_and_test(&ns->count))
                return;
-       namespace_lock();
-       br_write_lock(&vfsmount_lock);
-       umount_tree(ns->root, 0);
-       br_write_unlock(&vfsmount_lock);
-       namespace_unlock();
+       drop_collected_mounts(&ns->root->mnt);
        free_mnt_ns(ns);
 }
 
@@ -2881,7 +2893,7 @@ bool fs_fully_visible(struct file_system_type *type)
        if (unlikely(!ns))
                return false;
 
-       namespace_lock();
+       down_read(&namespace_sem);
        list_for_each_entry(mnt, &ns->list, mnt_list) {
                struct mount *child;
                if (mnt->mnt.mnt_sb->s_type != type)
@@ -2902,7 +2914,7 @@ bool fs_fully_visible(struct file_system_type *type)
        next:   ;
        }
 found:
-       namespace_unlock();
+       up_read(&namespace_sem);
        return visible;
 }