git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
[safe/jmp/linux-2.6]
/
fs
/
namespace.c
diff --git
a/fs/namespace.c
b/fs/namespace.c
index
a7bea8c
..
7d70d63
100644
(file)
--- a/
fs/namespace.c
+++ b/
fs/namespace.c
@@
-22,6
+22,7
@@
#include <linux/seq_file.h>
#include <linux/mnt_namespace.h>
#include <linux/namei.h>
#include <linux/seq_file.h>
#include <linux/mnt_namespace.h>
#include <linux/namei.h>
+#include <linux/nsproxy.h>
#include <linux/security.h>
#include <linux/mount.h>
#include <linux/ramfs.h>
#include <linux/security.h>
#include <linux/mount.h>
#include <linux/ramfs.h>
@@
-42,6
+43,8
@@
__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
static int event;
static DEFINE_IDA(mnt_id_ida);
static DEFINE_IDA(mnt_group_ida);
static int event;
static DEFINE_IDA(mnt_id_ida);
static DEFINE_IDA(mnt_group_ida);
+static int mnt_id_start = 0;
+static int mnt_group_start = 1;
static struct list_head *mount_hashtable __read_mostly;
static struct kmem_cache *mnt_cache __read_mostly;
static struct list_head *mount_hashtable __read_mostly;
static struct kmem_cache *mnt_cache __read_mostly;
@@
-69,7
+72,9
@@
static int mnt_alloc_id(struct vfsmount *mnt)
retry:
ida_pre_get(&mnt_id_ida, GFP_KERNEL);
spin_lock(&vfsmount_lock);
retry:
ida_pre_get(&mnt_id_ida, GFP_KERNEL);
spin_lock(&vfsmount_lock);
- res = ida_get_new(&mnt_id_ida, &mnt->mnt_id);
+ res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id);
+ if (!res)
+ mnt_id_start = mnt->mnt_id + 1;
spin_unlock(&vfsmount_lock);
if (res == -EAGAIN)
goto retry;
spin_unlock(&vfsmount_lock);
if (res == -EAGAIN)
goto retry;
@@
-79,8
+84,11
@@
retry:
static void mnt_free_id(struct vfsmount *mnt)
{
static void mnt_free_id(struct vfsmount *mnt)
{
+ int id = mnt->mnt_id;
spin_lock(&vfsmount_lock);
spin_lock(&vfsmount_lock);
- ida_remove(&mnt_id_ida, mnt->mnt_id);
+ ida_remove(&mnt_id_ida, id);
+ if (mnt_id_start > id)
+ mnt_id_start = id;
spin_unlock(&vfsmount_lock);
}
spin_unlock(&vfsmount_lock);
}
@@
-91,10
+99,18
@@
static void mnt_free_id(struct vfsmount *mnt)
*/
static int mnt_alloc_group_id(struct vfsmount *mnt)
{
*/
static int mnt_alloc_group_id(struct vfsmount *mnt)
{
+ int res;
+
if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
return -ENOMEM;
if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
return -ENOMEM;
- return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id);
+ res = ida_get_new_above(&mnt_group_ida,
+ mnt_group_start,
+ &mnt->mnt_group_id);
+ if (!res)
+ mnt_group_start = mnt->mnt_group_id + 1;
+
+ return res;
}
/*
}
/*
@@
-102,7
+118,10
@@
static int mnt_alloc_group_id(struct vfsmount *mnt)
*/
void mnt_release_group_id(struct vfsmount *mnt)
{
*/
void mnt_release_group_id(struct vfsmount *mnt)
{
- ida_remove(&mnt_group_ida, mnt->mnt_group_id);
+ int id = mnt->mnt_group_id;
+ ida_remove(&mnt_group_ida, id);
+ if (mnt_group_start > id)
+ mnt_group_start = id;
mnt->mnt_group_id = 0;
}
mnt->mnt_group_id = 0;
}
@@
-297,7
+316,8
@@
EXPORT_SYMBOL_GPL(mnt_clone_write);
*/
int mnt_want_write_file(struct file *file)
{
*/
int mnt_want_write_file(struct file *file)
{
- if (!(file->f_mode & FMODE_WRITE))
+ struct inode *inode = file->f_dentry->d_inode;
+ if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
return mnt_want_write(file->f_path.mnt);
else
return mnt_clone_write(file->f_path.mnt);
return mnt_want_write(file->f_path.mnt);
else
return mnt_clone_write(file->f_path.mnt);
@@
-1620,7
+1640,7
@@
static int do_new_mount(struct path *path, char *type, int flags,
{
struct vfsmount *mnt;
{
struct vfsmount *mnt;
- if (!type
|| !memchr(type, 0, PAGE_SIZE)
)
+ if (!type)
return -EINVAL;
/* we need capabilities... */
return -EINVAL;
/* we need capabilities... */
@@
-1851,6
+1871,23
@@
int copy_mount_options(const void __user * data, unsigned long *where)
return 0;
}
return 0;
}
+int copy_mount_string(const void __user *data, char **where)
+{
+ char *tmp;
+
+ if (!data) {
+ *where = NULL;
+ return 0;
+ }
+
+ tmp = strndup_user(data, PAGE_SIZE);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ *where = tmp;
+ return 0;
+}
+
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
@@
-1880,12
+1917,20
@@
long do_mount(char *dev_name, char *dir_name, char *type_page,
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
- if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
- return -EINVAL;
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
+ /* ... and get the mountpoint */
+ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
+ if (retval)
+ return retval;
+
+ retval = security_sb_mount(dev_name, &path,
+ type_page, flags, data_page);
+ if (retval)
+ goto dput_out;
+
/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
@@
-1910,16
+1955,6
@@
long do_mount(char *dev_name, char *dir_name, char *type_page,
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
- /* ... and get the mountpoint */
- retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
- if (retval)
- return retval;
-
- retval = security_sb_mount(dev_name, &path,
- type_page, flags, data_page);
- if (retval)
- goto dput_out;
-
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
@@
-2050,40
+2085,42
@@
EXPORT_SYMBOL(create_mnt_ns);
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
- int retval;
+ int ret;
+ char *kernel_type;
+ char *kernel_dir;
+ char *kernel_dev;
unsigned long data_page;
unsigned long data_page;
- unsigned long type_page;
- unsigned long dev_page;
- char *dir_page;
- ret
val = copy_mount_options(type, &type_pag
e);
- if (ret
val
< 0)
-
return retval
;
+ ret
= copy_mount_string(type, &kernel_typ
e);
+ if (ret < 0)
+
goto out_type
;
- dir_page = getname(dir_name);
- retval = PTR_ERR(dir_page);
- if (IS_ERR(dir_page))
- goto out1;
+ kernel_dir = getname(dir_name);
+ if (IS_ERR(kernel_dir)) {
+ ret = PTR_ERR(kernel_dir);
+ goto out_dir;
+ }
- ret
val = copy_mount_options(dev_name, &dev_page
);
- if (ret
val
< 0)
- goto out
2
;
+ ret
= copy_mount_string(dev_name, &kernel_dev
);
+ if (ret < 0)
+ goto out
_dev
;
- ret
val
= copy_mount_options(data, &data_page);
- if (ret
val
< 0)
- goto out
3
;
+ ret = copy_mount_options(data, &data_page);
+ if (ret < 0)
+ goto out
_data
;
- retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
- flags, (void *)data_page);
- free_page(data_page);
+ ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
+ (void *) data_page);
-out3:
- free_page(dev_page);
-out2:
- putname(dir_page);
-out1:
- free_page(type_page);
- return retval;
+ free_page(data_page);
+out_data:
+ kfree(kernel_dev);
+out_dev:
+ putname(kernel_dir);
+out_dir:
+ kfree(kernel_type);
+out_type:
+ return ret;
}
/*
}
/*
@@
-2222,16
+2259,9
@@
static void __init init_mount_tree(void)
mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
panic("Can't create rootfs");
mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
panic("Can't create rootfs");
- ns =
kmalloc(sizeof(*ns), GFP_KERNEL
);
- if (
!ns
)
+ ns =
create_mnt_ns(mnt
);
+ if (
IS_ERR(ns)
)
panic("Can't allocate initial namespace");
panic("Can't allocate initial namespace");
- atomic_set(&ns->count, 1);
- INIT_LIST_HEAD(&ns->list);
- init_waitqueue_head(&ns->poll);
- ns->event = 0;
- list_add(&mnt->mnt_list, &ns->list);
- ns->root = mnt;
- mnt->mnt_ns = ns;
init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);
init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);