diff options
| author | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 11:08:42 -0400 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 11:08:42 -0400 |
| commit | 520c8b16505236fc82daa352e6c5e73cd9870cff (patch) | |
| tree | e61b78440874e083928821423e226c0ecc2d6647 /fs | |
| parent | bc27027a73e8b80376b51a1583ad1c7445605e8a (diff) | |
vfs: add renameat2 syscall
Add new renameat2 syscall, which is the same as renameat with an added
flags argument.
Pass flags to vfs_rename() and to i_op->rename() as well.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reviewed-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/cachefiles/namei.c | 2 | ||||
| -rw-r--r-- | fs/ecryptfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/namei.c | 34 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 2 |
4 files changed, 30 insertions, 10 deletions
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index ca65f39dc8dc..31088a969351 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
| @@ -396,7 +396,7 @@ try_again: | |||
| 396 | cachefiles_io_error(cache, "Rename security error %d", ret); | 396 | cachefiles_io_error(cache, "Rename security error %d", ret); |
| 397 | } else { | 397 | } else { |
| 398 | ret = vfs_rename(dir->d_inode, rep, | 398 | ret = vfs_rename(dir->d_inode, rep, |
| 399 | cache->graveyard->d_inode, grave, NULL); | 399 | cache->graveyard->d_inode, grave, NULL, 0); |
| 400 | if (ret != 0 && ret != -ENOMEM) | 400 | if (ret != 0 && ret != -ENOMEM) |
| 401 | cachefiles_io_error(cache, | 401 | cachefiles_io_error(cache, |
| 402 | "Rename failed with error %d", ret); | 402 | "Rename failed with error %d", ret); |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index b167ca48b8ee..d4a9431ec73c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -641,7 +641,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 641 | } | 641 | } |
| 642 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, | 642 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, |
| 643 | lower_new_dir_dentry->d_inode, lower_new_dentry, | 643 | lower_new_dir_dentry->d_inode, lower_new_dentry, |
| 644 | NULL); | 644 | NULL, 0); |
| 645 | if (rc) | 645 | if (rc) |
| 646 | goto out_lock; | 646 | goto out_lock; |
| 647 | if (target_inode) | 647 | if (target_inode) |
diff --git a/fs/namei.c b/fs/namei.c index 12b8f56ba942..ab4e48c4a80a 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -3980,6 +3980,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
| 3980 | * @new_dir: parent of destination | 3980 | * @new_dir: parent of destination |
| 3981 | * @new_dentry: destination | 3981 | * @new_dentry: destination |
| 3982 | * @delegated_inode: returns an inode needing a delegation break | 3982 | * @delegated_inode: returns an inode needing a delegation break |
| 3983 | * @flags: rename flags | ||
| 3983 | * | 3984 | * |
| 3984 | * The caller must hold multiple mutexes--see lock_rename()). | 3985 | * The caller must hold multiple mutexes--see lock_rename()). |
| 3985 | * | 3986 | * |
| @@ -4023,7 +4024,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname | |||
| 4023 | */ | 4024 | */ |
| 4024 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 4025 | int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| 4025 | struct inode *new_dir, struct dentry *new_dentry, | 4026 | struct inode *new_dir, struct dentry *new_dentry, |
| 4026 | struct inode **delegated_inode) | 4027 | struct inode **delegated_inode, unsigned int flags) |
| 4027 | { | 4028 | { |
| 4028 | int error; | 4029 | int error; |
| 4029 | bool is_dir = d_is_dir(old_dentry); | 4030 | bool is_dir = d_is_dir(old_dentry); |
| @@ -4048,6 +4049,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 4048 | if (!old_dir->i_op->rename) | 4049 | if (!old_dir->i_op->rename) |
| 4049 | return -EPERM; | 4050 | return -EPERM; |
| 4050 | 4051 | ||
| 4052 | if (flags && !old_dir->i_op->rename2) | ||
| 4053 | return -EINVAL; | ||
| 4054 | |||
| 4051 | /* | 4055 | /* |
| 4052 | * If we are going to change the parent - check write permissions, | 4056 | * If we are going to change the parent - check write permissions, |
| 4053 | * we'll need to flip '..'. | 4057 | * we'll need to flip '..'. |
| @@ -4093,7 +4097,13 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 4093 | goto out; | 4097 | goto out; |
| 4094 | } | 4098 | } |
| 4095 | } | 4099 | } |
| 4096 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 4100 | if (!flags) { |
| 4101 | error = old_dir->i_op->rename(old_dir, old_dentry, | ||
| 4102 | new_dir, new_dentry); | ||
| 4103 | } else { | ||
| 4104 | error = old_dir->i_op->rename2(old_dir, old_dentry, | ||
| 4105 | new_dir, new_dentry, flags); | ||
| 4106 | } | ||
| 4097 | if (error) | 4107 | if (error) |
| 4098 | goto out; | 4108 | goto out; |
| 4099 | 4109 | ||
| @@ -4118,8 +4128,8 @@ out: | |||
| 4118 | return error; | 4128 | return error; |
| 4119 | } | 4129 | } |
| 4120 | 4130 | ||
| 4121 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | 4131 | SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, |
| 4122 | int, newdfd, const char __user *, newname) | 4132 | int, newdfd, const char __user *, newname, unsigned int, flags) |
| 4123 | { | 4133 | { |
| 4124 | struct dentry *old_dir, *new_dir; | 4134 | struct dentry *old_dir, *new_dir; |
| 4125 | struct dentry *old_dentry, *new_dentry; | 4135 | struct dentry *old_dentry, *new_dentry; |
| @@ -4131,6 +4141,10 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
| 4131 | unsigned int lookup_flags = 0; | 4141 | unsigned int lookup_flags = 0; |
| 4132 | bool should_retry = false; | 4142 | bool should_retry = false; |
| 4133 | int error; | 4143 | int error; |
| 4144 | |||
| 4145 | if (flags) | ||
| 4146 | return -EINVAL; | ||
| 4147 | |||
| 4134 | retry: | 4148 | retry: |
| 4135 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); | 4149 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); |
| 4136 | if (IS_ERR(from)) { | 4150 | if (IS_ERR(from)) { |
| @@ -4202,8 +4216,8 @@ retry_deleg: | |||
| 4202 | if (error) | 4216 | if (error) |
| 4203 | goto exit5; | 4217 | goto exit5; |
| 4204 | error = vfs_rename(old_dir->d_inode, old_dentry, | 4218 | error = vfs_rename(old_dir->d_inode, old_dentry, |
| 4205 | new_dir->d_inode, new_dentry, | 4219 | new_dir->d_inode, new_dentry, |
| 4206 | &delegated_inode); | 4220 | &delegated_inode, flags); |
| 4207 | exit5: | 4221 | exit5: |
| 4208 | dput(new_dentry); | 4222 | dput(new_dentry); |
| 4209 | exit4: | 4223 | exit4: |
| @@ -4233,9 +4247,15 @@ exit: | |||
| 4233 | return error; | 4247 | return error; |
| 4234 | } | 4248 | } |
| 4235 | 4249 | ||
| 4250 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | ||
| 4251 | int, newdfd, const char __user *, newname) | ||
| 4252 | { | ||
| 4253 | return sys_renameat2(olddfd, oldname, newdfd, newname, 0); | ||
| 4254 | } | ||
| 4255 | |||
| 4236 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) | 4256 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) |
| 4237 | { | 4257 | { |
| 4238 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); | 4258 | return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
| 4239 | } | 4259 | } |
| 4240 | 4260 | ||
| 4241 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) | 4261 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6d7be3f80356..915808b36df7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -1694,7 +1694,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1694 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) | 1694 | if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) |
| 1695 | goto out_dput_new; | 1695 | goto out_dput_new; |
| 1696 | 1696 | ||
| 1697 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); | 1697 | host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL, 0); |
| 1698 | if (!host_err) { | 1698 | if (!host_err) { |
| 1699 | host_err = commit_metadata(tfhp); | 1699 | host_err = commit_metadata(tfhp); |
| 1700 | if (!host_err) | 1700 | if (!host_err) |
