aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 2dd333b0fe7f..7230787d18b0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -22,6 +22,7 @@
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/mnt_namespace.h> 23#include <linux/mnt_namespace.h>
24#include <linux/namei.h> 24#include <linux/namei.h>
25#include <linux/nsproxy.h>
25#include <linux/security.h> 26#include <linux/security.h>
26#include <linux/mount.h> 27#include <linux/mount.h>
27#include <linux/ramfs.h> 28#include <linux/ramfs.h>
@@ -42,6 +43,8 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
42static int event; 43static int event;
43static DEFINE_IDA(mnt_id_ida); 44static DEFINE_IDA(mnt_id_ida);
44static DEFINE_IDA(mnt_group_ida); 45static DEFINE_IDA(mnt_group_ida);
46static int mnt_id_start = 0;
47static int mnt_group_start = 1;
45 48
46static struct list_head *mount_hashtable __read_mostly; 49static struct list_head *mount_hashtable __read_mostly;
47static struct kmem_cache *mnt_cache __read_mostly; 50static struct kmem_cache *mnt_cache __read_mostly;
@@ -69,7 +72,9 @@ static int mnt_alloc_id(struct vfsmount *mnt)
69retry: 72retry:
70 ida_pre_get(&mnt_id_ida, GFP_KERNEL); 73 ida_pre_get(&mnt_id_ida, GFP_KERNEL);
71 spin_lock(&vfsmount_lock); 74 spin_lock(&vfsmount_lock);
72 res = ida_get_new(&mnt_id_ida, &mnt->mnt_id); 75 res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id);
76 if (!res)
77 mnt_id_start = mnt->mnt_id + 1;
73 spin_unlock(&vfsmount_lock); 78 spin_unlock(&vfsmount_lock);
74 if (res == -EAGAIN) 79 if (res == -EAGAIN)
75 goto retry; 80 goto retry;
@@ -79,8 +84,11 @@ retry:
79 84
80static void mnt_free_id(struct vfsmount *mnt) 85static void mnt_free_id(struct vfsmount *mnt)
81{ 86{
87 int id = mnt->mnt_id;
82 spin_lock(&vfsmount_lock); 88 spin_lock(&vfsmount_lock);
83 ida_remove(&mnt_id_ida, mnt->mnt_id); 89 ida_remove(&mnt_id_ida, id);
90 if (mnt_id_start > id)
91 mnt_id_start = id;
84 spin_unlock(&vfsmount_lock); 92 spin_unlock(&vfsmount_lock);
85} 93}
86 94
@@ -91,10 +99,18 @@ static void mnt_free_id(struct vfsmount *mnt)
91 */ 99 */
92static int mnt_alloc_group_id(struct vfsmount *mnt) 100static int mnt_alloc_group_id(struct vfsmount *mnt)
93{ 101{
102 int res;
103
94 if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL)) 104 if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
95 return -ENOMEM; 105 return -ENOMEM;
96 106
97 return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id); 107 res = ida_get_new_above(&mnt_group_ida,
108 mnt_group_start,
109 &mnt->mnt_group_id);
110 if (!res)
111 mnt_group_start = mnt->mnt_group_id + 1;
112
113 return res;
98} 114}
99 115
100/* 116/*
@@ -102,7 +118,10 @@ static int mnt_alloc_group_id(struct vfsmount *mnt)
102 */ 118 */
103void mnt_release_group_id(struct vfsmount *mnt) 119void mnt_release_group_id(struct vfsmount *mnt)
104{ 120{
105 ida_remove(&mnt_group_ida, mnt->mnt_group_id); 121 int id = mnt->mnt_group_id;
122 ida_remove(&mnt_group_ida, id);
123 if (mnt_group_start > id)
124 mnt_group_start = id;
106 mnt->mnt_group_id = 0; 125 mnt->mnt_group_id = 0;
107} 126}
108 127
@@ -297,7 +316,8 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
297 */ 316 */
298int mnt_want_write_file(struct file *file) 317int mnt_want_write_file(struct file *file)
299{ 318{
300 if (!(file->f_mode & FMODE_WRITE)) 319 struct inode *inode = file->f_dentry->d_inode;
320 if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
301 return mnt_want_write(file->f_path.mnt); 321 return mnt_want_write(file->f_path.mnt);
302 else 322 else
303 return mnt_clone_write(file->f_path.mnt); 323 return mnt_clone_write(file->f_path.mnt);
@@ -1937,6 +1957,21 @@ dput_out:
1937 return retval; 1957 return retval;
1938} 1958}
1939 1959
1960static struct mnt_namespace *alloc_mnt_ns(void)
1961{
1962 struct mnt_namespace *new_ns;
1963
1964 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
1965 if (!new_ns)
1966 return ERR_PTR(-ENOMEM);
1967 atomic_set(&new_ns->count, 1);
1968 new_ns->root = NULL;
1969 INIT_LIST_HEAD(&new_ns->list);
1970 init_waitqueue_head(&new_ns->poll);
1971 new_ns->event = 0;
1972 return new_ns;
1973}
1974
1940/* 1975/*
1941 * Allocate a new namespace structure and populate it with contents 1976 * Allocate a new namespace structure and populate it with contents
1942 * copied from the namespace of the passed in task structure. 1977 * copied from the namespace of the passed in task structure.
@@ -1948,14 +1983,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
1948 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; 1983 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
1949 struct vfsmount *p, *q; 1984 struct vfsmount *p, *q;
1950 1985
1951 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); 1986 new_ns = alloc_mnt_ns();
1952 if (!new_ns) 1987 if (IS_ERR(new_ns))
1953 return ERR_PTR(-ENOMEM); 1988 return new_ns;
1954
1955 atomic_set(&new_ns->count, 1);
1956 INIT_LIST_HEAD(&new_ns->list);
1957 init_waitqueue_head(&new_ns->poll);
1958 new_ns->event = 0;
1959 1989
1960 down_write(&namespace_sem); 1990 down_write(&namespace_sem);
1961 /* First pass: copy the tree topology */ 1991 /* First pass: copy the tree topology */
@@ -2019,6 +2049,24 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
2019 return new_ns; 2049 return new_ns;
2020} 2050}
2021 2051
2052/**
2053 * create_mnt_ns - creates a private namespace and adds a root filesystem
2054 * @mnt: pointer to the new root filesystem mountpoint
2055 */
2056struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
2057{
2058 struct mnt_namespace *new_ns;
2059
2060 new_ns = alloc_mnt_ns();
2061 if (!IS_ERR(new_ns)) {
2062 mnt->mnt_ns = new_ns;
2063 new_ns->root = mnt;
2064 list_add(&new_ns->list, &new_ns->root->mnt_list);
2065 }
2066 return new_ns;
2067}
2068EXPORT_SYMBOL(create_mnt_ns);
2069
2022SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, 2070SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2023 char __user *, type, unsigned long, flags, void __user *, data) 2071 char __user *, type, unsigned long, flags, void __user *, data)
2024{ 2072{
@@ -2194,16 +2242,9 @@ static void __init init_mount_tree(void)
2194 mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); 2242 mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
2195 if (IS_ERR(mnt)) 2243 if (IS_ERR(mnt))
2196 panic("Can't create rootfs"); 2244 panic("Can't create rootfs");
2197 ns = kmalloc(sizeof(*ns), GFP_KERNEL); 2245 ns = create_mnt_ns(mnt);
2198 if (!ns) 2246 if (IS_ERR(ns))
2199 panic("Can't allocate initial namespace"); 2247 panic("Can't allocate initial namespace");
2200 atomic_set(&ns->count, 1);
2201 INIT_LIST_HEAD(&ns->list);
2202 init_waitqueue_head(&ns->poll);
2203 ns->event = 0;
2204 list_add(&mnt->mnt_list, &ns->list);
2205 ns->root = mnt;
2206 mnt->mnt_ns = ns;
2207 2248
2208 init_task.nsproxy->mnt_ns = ns; 2249 init_task.nsproxy->mnt_ns = ns;
2209 get_mnt_ns(ns); 2250 get_mnt_ns(ns);
@@ -2246,10 +2287,14 @@ void __init mnt_init(void)
2246 init_mount_tree(); 2287 init_mount_tree();
2247} 2288}
2248 2289
2249void __put_mnt_ns(struct mnt_namespace *ns) 2290void put_mnt_ns(struct mnt_namespace *ns)
2250{ 2291{
2251 struct vfsmount *root = ns->root; 2292 struct vfsmount *root;
2252 LIST_HEAD(umount_list); 2293 LIST_HEAD(umount_list);
2294
2295 if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock))
2296 return;
2297 root = ns->root;
2253 ns->root = NULL; 2298 ns->root = NULL;
2254 spin_unlock(&vfsmount_lock); 2299 spin_unlock(&vfsmount_lock);
2255 down_write(&namespace_sem); 2300 down_write(&namespace_sem);
@@ -2260,3 +2305,4 @@ void __put_mnt_ns(struct mnt_namespace *ns)
2260 release_mounts(&umount_list); 2305 release_mounts(&umount_list);
2261 kfree(ns); 2306 kfree(ns);
2262} 2307}
2308EXPORT_SYMBOL(put_mnt_ns);