aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-07-19 18:25:00 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-29 13:24:15 -0400
commita8104a9fcdeb82e22d7acd55fca20746581067d3 (patch)
tree3036dae685f9b12a878dd02e439f0050114d7745
parent8e4bfca1d1f0de62301dd223675717e7a5f63a27 (diff)
pull mnt_want_write()/mnt_drop_write() into kern_path_create()/done_path_create() resp.
One side effect - attempt to create a cross-device link on a read-only fs fails with EROFS instead of EXDEV now. Makes more sense, POSIX allows, etc. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c57
-rw-r--r--fs/ocfs2/refcounttree.c7
-rw-r--r--net/unix/af_unix.c4
3 files changed, 18 insertions, 50 deletions
diff --git a/fs/namei.c b/fs/namei.c
index cf362dc9d1fd..a3fb78fd70d2 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2865,10 +2865,11 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
2865 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 2865 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2866 dentry = lookup_hash(&nd); 2866 dentry = lookup_hash(&nd);
2867 if (IS_ERR(dentry)) 2867 if (IS_ERR(dentry))
2868 goto fail; 2868 goto unlock;
2869 2869
2870 error = -EEXIST;
2870 if (dentry->d_inode) 2871 if (dentry->d_inode)
2871 goto eexist; 2872 goto fail;
2872 /* 2873 /*
2873 * Special case - lookup gave negative, but... we had foo/bar/ 2874 * Special case - lookup gave negative, but... we had foo/bar/
2874 * From the vfs_mknod() POV we just have a negative dentry - 2875 * From the vfs_mknod() POV we just have a negative dentry -
@@ -2876,16 +2877,18 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
2876 * been asking for (non-existent) directory. -ENOENT for you. 2877 * been asking for (non-existent) directory. -ENOENT for you.
2877 */ 2878 */
2878 if (unlikely(!is_dir && nd.last.name[nd.last.len])) { 2879 if (unlikely(!is_dir && nd.last.name[nd.last.len])) {
2879 dput(dentry); 2880 error = -ENOENT;
2880 dentry = ERR_PTR(-ENOENT);
2881 goto fail; 2881 goto fail;
2882 } 2882 }
2883 error = mnt_want_write(nd.path.mnt);
2884 if (error)
2885 goto fail;
2883 *path = nd.path; 2886 *path = nd.path;
2884 return dentry; 2887 return dentry;
2885eexist:
2886 dput(dentry);
2887 dentry = ERR_PTR(-EEXIST);
2888fail: 2888fail:
2889 dput(dentry);
2890 dentry = ERR_PTR(error);
2891unlock:
2889 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2892 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2890out: 2893out:
2891 path_put(&nd.path); 2894 path_put(&nd.path);
@@ -2897,6 +2900,7 @@ void done_path_create(struct path *path, struct dentry *dentry)
2897{ 2900{
2898 dput(dentry); 2901 dput(dentry);
2899 mutex_unlock(&path->dentry->d_inode->i_mutex); 2902 mutex_unlock(&path->dentry->d_inode->i_mutex);
2903 mnt_drop_write(path->mnt);
2900 path_put(path); 2904 path_put(path);
2901} 2905}
2902EXPORT_SYMBOL(done_path_create); 2906EXPORT_SYMBOL(done_path_create);
@@ -2974,12 +2978,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
2974 2978
2975 if (!IS_POSIXACL(path.dentry->d_inode)) 2979 if (!IS_POSIXACL(path.dentry->d_inode))
2976 mode &= ~current_umask(); 2980 mode &= ~current_umask();
2977 error = mnt_want_write(path.mnt);
2978 if (error)
2979 goto out_dput;
2980 error = security_path_mknod(&path, dentry, mode, dev); 2981 error = security_path_mknod(&path, dentry, mode, dev);
2981 if (error) 2982 if (error)
2982 goto out_drop_write; 2983 goto out;
2983 switch (mode & S_IFMT) { 2984 switch (mode & S_IFMT) {
2984 case 0: case S_IFREG: 2985 case 0: case S_IFREG:
2985 error = vfs_create(path.dentry->d_inode,dentry,mode,true); 2986 error = vfs_create(path.dentry->d_inode,dentry,mode,true);
@@ -2992,11 +2993,8 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
2992 error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); 2993 error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
2993 break; 2994 break;
2994 } 2995 }
2995out_drop_write: 2996out:
2996 mnt_drop_write(path.mnt);
2997out_dput:
2998 done_path_create(&path, dentry); 2997 done_path_create(&path, dentry);
2999
3000 return error; 2998 return error;
3001} 2999}
3002 3000
@@ -3042,16 +3040,9 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
3042 3040
3043 if (!IS_POSIXACL(path.dentry->d_inode)) 3041 if (!IS_POSIXACL(path.dentry->d_inode))
3044 mode &= ~current_umask(); 3042 mode &= ~current_umask();
3045 error = mnt_want_write(path.mnt);
3046 if (error)
3047 goto out_dput;
3048 error = security_path_mkdir(&path, dentry, mode); 3043 error = security_path_mkdir(&path, dentry, mode);
3049 if (error) 3044 if (!error)
3050 goto out_drop_write; 3045 error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
3051 error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
3052out_drop_write:
3053 mnt_drop_write(path.mnt);
3054out_dput:
3055 done_path_create(&path, dentry); 3046 done_path_create(&path, dentry);
3056 return error; 3047 return error;
3057} 3048}
@@ -3326,16 +3317,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
3326 if (IS_ERR(dentry)) 3317 if (IS_ERR(dentry))
3327 goto out_putname; 3318 goto out_putname;
3328 3319
3329 error = mnt_want_write(path.mnt);
3330 if (error)
3331 goto out_dput;
3332 error = security_path_symlink(&path, dentry, from); 3320 error = security_path_symlink(&path, dentry, from);
3333 if (error) 3321 if (!error)
3334 goto out_drop_write; 3322 error = vfs_symlink(path.dentry->d_inode, dentry, from);
3335 error = vfs_symlink(path.dentry->d_inode, dentry, from);
3336out_drop_write:
3337 mnt_drop_write(path.mnt);
3338out_dput:
3339 done_path_create(&path, dentry); 3323 done_path_create(&path, dentry);
3340out_putname: 3324out_putname:
3341 putname(from); 3325 putname(from);
@@ -3436,15 +3420,10 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
3436 error = -EXDEV; 3420 error = -EXDEV;
3437 if (old_path.mnt != new_path.mnt) 3421 if (old_path.mnt != new_path.mnt)
3438 goto out_dput; 3422 goto out_dput;
3439 error = mnt_want_write(new_path.mnt);
3440 if (error)
3441 goto out_dput;
3442 error = security_path_link(old_path.dentry, &new_path, new_dentry); 3423 error = security_path_link(old_path.dentry, &new_path, new_dentry);
3443 if (error) 3424 if (error)
3444 goto out_drop_write; 3425 goto out_dput;
3445 error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); 3426 error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
3446out_drop_write:
3447 mnt_drop_write(new_path.mnt);
3448out_dput: 3427out_dput:
3449 done_path_create(&new_path, new_dentry); 3428 done_path_create(&new_path, new_dentry);
3450out: 3429out:
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 23cf78f68503..30a055049e16 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -4466,16 +4466,9 @@ int ocfs2_reflink_ioctl(struct inode *inode,
4466 goto out_dput; 4466 goto out_dput;
4467 } 4467 }
4468 4468
4469 error = mnt_want_write(new_path.mnt);
4470 if (error) {
4471 mlog_errno(error);
4472 goto out_dput;
4473 }
4474
4475 error = ocfs2_vfs_reflink(old_path.dentry, 4469 error = ocfs2_vfs_reflink(old_path.dentry,
4476 new_path.dentry->d_inode, 4470 new_path.dentry->d_inode,
4477 new_dentry, preserve); 4471 new_dentry, preserve);
4478 mnt_drop_write(new_path.mnt);
4479out_dput: 4472out_dput:
4480 done_path_create(&new_path, new_dentry); 4473 done_path_create(&new_path, new_dentry);
4481out: 4474out:
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e8239540683a..88ab72820b9f 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -876,15 +876,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
876 */ 876 */
877 mode = S_IFSOCK | 877 mode = S_IFSOCK |
878 (SOCK_INODE(sock)->i_mode & ~current_umask()); 878 (SOCK_INODE(sock)->i_mode & ~current_umask());
879 err = mnt_want_write(path.mnt);
880 if (err)
881 goto out_mknod_dput;
882 err = security_path_mknod(&path, dentry, mode, 0); 879 err = security_path_mknod(&path, dentry, mode, 0);
883 if (err) 880 if (err)
884 goto out_mknod_drop_write; 881 goto out_mknod_drop_write;
885 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); 882 err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
886out_mknod_drop_write: 883out_mknod_drop_write:
887 mnt_drop_write(path.mnt);
888 if (err) 884 if (err)
889 goto out_mknod_dput; 885 goto out_mknod_dput;
890 mntget(path.mnt); 886 mntget(path.mnt);