aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c57
1 files changed, 18 insertions, 39 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: