aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/filesystems/Locking6
-rw-r--r--Documentation/filesystems/vfs.txt16
-rw-r--r--arch/x86/syscalls/syscall_64.tbl1
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_compat25.h4
-rw-r--r--drivers/staging/lustre/lustre/lvfs/lvfs_linux.c2
-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
-rw-r--r--include/linux/fs.h4
10 files changed, 58 insertions, 15 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 5b0c083d7c0e..f424e0e5b46b 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -47,6 +47,8 @@ prototypes:
47 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 47 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
48 int (*rename) (struct inode *, struct dentry *, 48 int (*rename) (struct inode *, struct dentry *,
49 struct inode *, struct dentry *); 49 struct inode *, struct dentry *);
50 int (*rename2) (struct inode *, struct dentry *,
51 struct inode *, struct dentry *, unsigned int);
50 int (*readlink) (struct dentry *, char __user *,int); 52 int (*readlink) (struct dentry *, char __user *,int);
51 void * (*follow_link) (struct dentry *, struct nameidata *); 53 void * (*follow_link) (struct dentry *, struct nameidata *);
52 void (*put_link) (struct dentry *, struct nameidata *, void *); 54 void (*put_link) (struct dentry *, struct nameidata *, void *);
@@ -78,6 +80,7 @@ mkdir: yes
78unlink: yes (both) 80unlink: yes (both)
79rmdir: yes (both) (see below) 81rmdir: yes (both) (see below)
80rename: yes (all) (see below) 82rename: yes (all) (see below)
83rename2: yes (all) (see below)
81readlink: no 84readlink: no
82follow_link: no 85follow_link: no
83put_link: no 86put_link: no
@@ -96,7 +99,8 @@ tmpfile: no
96 99
97 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on 100 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
98victim. 101victim.
99 cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. 102 cross-directory ->rename() and rename2() has (per-superblock)
103->s_vfs_rename_sem.
100 104
101See Documentation/filesystems/directory-locking for more detailed discussion 105See Documentation/filesystems/directory-locking for more detailed discussion
102of the locking scheme for directory operations. 106of the locking scheme for directory operations.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index c53784c119c8..94eb86287bcb 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -347,6 +347,8 @@ struct inode_operations {
347 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 347 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
348 int (*rename) (struct inode *, struct dentry *, 348 int (*rename) (struct inode *, struct dentry *,
349 struct inode *, struct dentry *); 349 struct inode *, struct dentry *);
350 int (*rename2) (struct inode *, struct dentry *,
351 struct inode *, struct dentry *, unsigned int);
350 int (*readlink) (struct dentry *, char __user *,int); 352 int (*readlink) (struct dentry *, char __user *,int);
351 void * (*follow_link) (struct dentry *, struct nameidata *); 353 void * (*follow_link) (struct dentry *, struct nameidata *);
352 void (*put_link) (struct dentry *, struct nameidata *, void *); 354 void (*put_link) (struct dentry *, struct nameidata *, void *);
@@ -414,6 +416,20 @@ otherwise noted.
414 rename: called by the rename(2) system call to rename the object to 416 rename: called by the rename(2) system call to rename the object to
415 have the parent and name given by the second inode and dentry. 417 have the parent and name given by the second inode and dentry.
416 418
419 rename2: this has an additional flags argument compared to rename.
420 If no flags are supported by the filesystem then this method
421 need not be implemented. If some flags are supported then the
422 filesystem must return -EINVAL for any unsupported or unknown
423 flags. Currently the following flags are implemented:
424 (1) RENAME_NOREPLACE: this flag indicates that if the target
425 of the rename exists the rename should fail with -EEXIST
426 instead of replacing the target. The VFS already checks for
427 existence, so for local filesystems the RENAME_NOREPLACE
428 implementation is equivalent to plain rename.
429 (2) RENAME_EXCHANGE: exchange source and target. Both must
430 exist; this is checked by the VFS. Unlike plain rename,
431 source and target may be of different type.
432
417 readlink: called by the readlink(2) system call. Only required if 433 readlink: called by the readlink(2) system call. Only required if
418 you want to support reading symbolic links 434 you want to support reading symbolic links
419 435
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index a12bddc7ccea..04376ac3d9ef 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -322,6 +322,7 @@
322313 common finit_module sys_finit_module 322313 common finit_module sys_finit_module
323314 common sched_setattr sys_sched_setattr 323314 common sched_setattr sys_sched_setattr
324315 common sched_getattr sys_sched_getattr 324315 common sched_getattr sys_sched_getattr
325316 common renameat2 sys_renameat2
325 326
326# 327#
327# x32-specific system call numbers start at 512 to avoid cache impact 328# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
index eefdb8d061b1..81cc7a0134bb 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
@@ -105,8 +105,8 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
105#define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry) 105#define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry)
106#define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev) 106#define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev)
107#define ll_security_inode_unlink(dir,entry,mnt) security_inode_unlink(dir,entry) 107#define ll_security_inode_unlink(dir,entry,mnt) security_inode_unlink(dir,entry)
108#define ll_vfs_rename(old,old_dir,mnt,new,new_dir,mnt1,delegated_inode) \ 108#define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \
109 vfs_rename(old,old_dir,new,new_dir,delegated_inode) 109 vfs_rename(old, old_dir, new, new_dir, NULL, 0)
110 110
111#define cfs_bio_io_error(a,b) bio_io_error((a)) 111#define cfs_bio_io_error(a,b) bio_io_error((a))
112#define cfs_bio_endio(a,b,c) bio_endio((a),(c)) 112#define cfs_bio_endio(a,b,c) bio_endio((a),(c))
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
index 428ffd8c37b7..d50822be3230 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
@@ -223,7 +223,7 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt,
223 GOTO(put_old, err = PTR_ERR(dchild_new)); 223 GOTO(put_old, err = PTR_ERR(dchild_new));
224 224
225 err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, 225 err = ll_vfs_rename(dir->d_inode, dchild_old, mnt,
226 dir->d_inode, dchild_new, mnt, NULL); 226 dir->d_inode, dchild_new, mnt);
227 227
228 dput(dchild_new); 228 dput(dchild_new);
229put_old: 229put_old:
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)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 23b2a35d712e..3b3670e97da6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1460,7 +1460,7 @@ extern int vfs_symlink(struct inode *, struct dentry *, const char *);
1460extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); 1460extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **);
1461extern int vfs_rmdir(struct inode *, struct dentry *); 1461extern int vfs_rmdir(struct inode *, struct dentry *);
1462extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); 1462extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
1463extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **); 1463extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
1464 1464
1465/* 1465/*
1466 * VFS dentry helper functions. 1466 * VFS dentry helper functions.
@@ -1571,6 +1571,8 @@ struct inode_operations {
1571 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 1571 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
1572 int (*rename) (struct inode *, struct dentry *, 1572 int (*rename) (struct inode *, struct dentry *,
1573 struct inode *, struct dentry *); 1573 struct inode *, struct dentry *);
1574 int (*rename2) (struct inode *, struct dentry *,
1575 struct inode *, struct dentry *, unsigned int);
1574 int (*setattr) (struct dentry *, struct iattr *); 1576 int (*setattr) (struct dentry *, struct iattr *);
1575 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1577 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1576 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); 1578 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);