aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 20:11:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 20:11:47 -0500
commit33caf82acf4dc420bf0f0136b886f7b27ecf90c5 (patch)
treeb24b0b5c8f257ae7db3b8df939821a0856869895 /fs/namespace.c
parentca9706a282943899981e83604f2ed13e88ce4239 (diff)
parentbbddca8e8fac07ece3938e03526b5d00fa791a4c (diff)
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: "All kinds of stuff. That probably should've been 5 or 6 separate branches, but by the time I'd realized how large and mixed that bag had become it had been too close to -final to play with rebasing. Some fs/namei.c cleanups there, memdup_user_nul() introduction and switching open-coded instances, burying long-dead code, whack-a-mole of various kinds, several new helpers for ->llseek(), assorted cleanups and fixes from various people, etc. One piece probably deserves special mention - Neil's lookup_one_len_unlocked(). Similar to lookup_one_len(), but gets called without ->i_mutex and tries to avoid ever taking it. That, of course, means that it's not useful for any directory modifications, but things like getting inode attributes in nfds readdirplus are fine with that. I really should've asked for moratorium on lookup-related changes this cycle, but since I hadn't done that early enough... I *am* asking for that for the coming cycle, though - I'm going to try and get conversion of i_mutex to rwsem with ->lookup() done under lock taken shared. There will be a patch closer to the end of the window, along the lines of the one Linus had posted last May - mechanical conversion of ->i_mutex accesses to inode_lock()/inode_unlock()/inode_trylock()/ inode_is_locked()/inode_lock_nested(). To quote Linus back then: ----- | This is an automated patch using | | sed 's/mutex_lock(&\(.*\)->i_mutex)/inode_lock(\1)/' | sed 's/mutex_unlock(&\(.*\)->i_mutex)/inode_unlock(\1)/' | sed 's/mutex_lock_nested(&\(.*\)->i_mutex,[ ]*I_MUTEX_\([A-Z0-9_]*\))/inode_lock_nested(\1, I_MUTEX_\2)/' | sed 's/mutex_is_locked(&\(.*\)->i_mutex)/inode_is_locked(\1)/' | sed 's/mutex_trylock(&\(.*\)->i_mutex)/inode_trylock(\1)/' | | with a very few manual fixups ----- I'm going to send that once the ->i_mutex-affecting stuff in -next gets mostly merged (or when Linus says he's about to stop taking merges)" * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits) nfsd: don't hold i_mutex over userspace upcalls fs:affs:Replace time_t with time64_t fs/9p: use fscache mutex rather than spinlock proc: add a reschedule point in proc_readfd_common() logfs: constify logfs_block_ops structures fcntl: allow to set O_DIRECT flag on pipe fs: __generic_file_splice_read retry lookup on AOP_TRUNCATED_PAGE fs: xattr: Use kvfree() [s390] page_to_phys() always returns a multiple of PAGE_SIZE nbd: use ->compat_ioctl() fs: use block_device name vsprintf helper lib/vsprintf: add %*pg format specifier fs: use gendisk->disk_name where possible poll: plug an unused argument to do_poll amdkfd: don't open-code memdup_user() cdrom: don't open-code memdup_user() rsxx: don't open-code memdup_user() mtip32xx: don't open-code memdup_user() [um] mconsole: don't open-code memdup_user_nul() [um] hostaudio: don't open-code memdup_user() ...
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 4d2c8f64b7bf..a830e1463704 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2609,18 +2609,18 @@ static long exact_copy_from_user(void *to, const void __user * from,
2609 return n; 2609 return n;
2610} 2610}
2611 2611
2612int copy_mount_options(const void __user * data, unsigned long *where) 2612void *copy_mount_options(const void __user * data)
2613{ 2613{
2614 int i; 2614 int i;
2615 unsigned long page;
2616 unsigned long size; 2615 unsigned long size;
2616 char *copy;
2617 2617
2618 *where = 0;
2619 if (!data) 2618 if (!data)
2620 return 0; 2619 return NULL;
2621 2620
2622 if (!(page = __get_free_page(GFP_KERNEL))) 2621 copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
2623 return -ENOMEM; 2622 if (!copy)
2623 return ERR_PTR(-ENOMEM);
2624 2624
2625 /* We only care that *some* data at the address the user 2625 /* We only care that *some* data at the address the user
2626 * gave us is valid. Just in case, we'll zero 2626 * gave us is valid. Just in case, we'll zero
@@ -2631,15 +2631,14 @@ int copy_mount_options(const void __user * data, unsigned long *where)
2631 if (size > PAGE_SIZE) 2631 if (size > PAGE_SIZE)
2632 size = PAGE_SIZE; 2632 size = PAGE_SIZE;
2633 2633
2634 i = size - exact_copy_from_user((void *)page, data, size); 2634 i = size - exact_copy_from_user(copy, data, size);
2635 if (!i) { 2635 if (!i) {
2636 free_page(page); 2636 kfree(copy);
2637 return -EFAULT; 2637 return ERR_PTR(-EFAULT);
2638 } 2638 }
2639 if (i != PAGE_SIZE) 2639 if (i != PAGE_SIZE)
2640 memset((char *)page + i, 0, PAGE_SIZE - i); 2640 memset(copy + i, 0, PAGE_SIZE - i);
2641 *where = page; 2641 return copy;
2642 return 0;
2643} 2642}
2644 2643
2645char *copy_mount_string(const void __user *data) 2644char *copy_mount_string(const void __user *data)
@@ -2906,7 +2905,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2906 int ret; 2905 int ret;
2907 char *kernel_type; 2906 char *kernel_type;
2908 char *kernel_dev; 2907 char *kernel_dev;
2909 unsigned long data_page; 2908 void *options;
2910 2909
2911 kernel_type = copy_mount_string(type); 2910 kernel_type = copy_mount_string(type);
2912 ret = PTR_ERR(kernel_type); 2911 ret = PTR_ERR(kernel_type);
@@ -2918,14 +2917,14 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2918 if (IS_ERR(kernel_dev)) 2917 if (IS_ERR(kernel_dev))
2919 goto out_dev; 2918 goto out_dev;
2920 2919
2921 ret = copy_mount_options(data, &data_page); 2920 options = copy_mount_options(data);
2922 if (ret < 0) 2921 ret = PTR_ERR(options);
2922 if (IS_ERR(options))
2923 goto out_data; 2923 goto out_data;
2924 2924
2925 ret = do_mount(kernel_dev, dir_name, kernel_type, flags, 2925 ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
2926 (void *) data_page);
2927 2926
2928 free_page(data_page); 2927 kfree(options);
2929out_data: 2928out_data:
2930 kfree(kernel_dev); 2929 kfree(kernel_dev);
2931out_dev: 2930out_dev:
@@ -2949,9 +2948,9 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
2949 return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); 2948 return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
2950} 2949}
2951 2950
2952int path_is_under(struct path *path1, struct path *path2) 2951bool path_is_under(struct path *path1, struct path *path2)
2953{ 2952{
2954 int res; 2953 bool res;
2955 read_seqlock_excl(&mount_lock); 2954 read_seqlock_excl(&mount_lock);
2956 res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); 2955 res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
2957 read_sequnlock_excl(&mount_lock); 2956 read_sequnlock_excl(&mount_lock);