aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:42 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:42 -0400
commit520c8b16505236fc82daa352e6c5e73cd9870cff (patch)
treee61b78440874e083928821423e226c0ecc2d6647 /fs
parentbc27027a73e8b80376b51a1583ad1c7445605e8a (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.c2
-rw-r--r--fs/ecryptfs/inode.c2
-rw-r--r--fs/namei.c34
-rw-r--r--fs/nfsd/vfs.c2
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 */
4024int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 4025int 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
4121SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, 4131SYSCALL_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
4134retry: 4148retry:
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);
4207exit5: 4221exit5:
4208 dput(new_dentry); 4222 dput(new_dentry);
4209exit4: 4223exit4:
@@ -4233,9 +4247,15 @@ exit:
4233 return error; 4247 return error;
4234} 4248}
4235 4249
4250SYSCALL_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
4236SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) 4256SYSCALL_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
4241int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) 4261int 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)