Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+58 -15
+5 -1
Documentation/filesystems/Locking
··· 47 47 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 48 48 int (*rename) (struct inode *, struct dentry *, 49 49 struct inode *, struct dentry *); 50 + int (*rename2) (struct inode *, struct dentry *, 51 + struct inode *, struct dentry *, unsigned int); 50 52 int (*readlink) (struct dentry *, char __user *,int); 51 53 void * (*follow_link) (struct dentry *, struct nameidata *); 52 54 void (*put_link) (struct dentry *, struct nameidata *, void *); ··· 80 78 unlink: yes (both) 81 79 rmdir: yes (both) (see below) 82 80 rename: yes (all) (see below) 81 + rename2: yes (all) (see below) 83 82 readlink: no 84 83 follow_link: no 85 84 put_link: no ··· 99 96 100 97 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on 101 98 victim. 102 - cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. 99 + cross-directory ->rename() and rename2() has (per-superblock) 100 + ->s_vfs_rename_sem. 103 101 104 102 See Documentation/filesystems/directory-locking for more detailed discussion 105 103 of the locking scheme for directory operations.
+16
Documentation/filesystems/vfs.txt
··· 347 347 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 348 348 int (*rename) (struct inode *, struct dentry *, 349 349 struct inode *, struct dentry *); 350 + int (*rename2) (struct inode *, struct dentry *, 351 + struct inode *, struct dentry *, unsigned int); 350 352 int (*readlink) (struct dentry *, char __user *,int); 351 353 void * (*follow_link) (struct dentry *, struct nameidata *); 352 354 void (*put_link) (struct dentry *, struct nameidata *, void *); ··· 415 413 416 414 rename: called by the rename(2) system call to rename the object to 417 415 have the parent and name given by the second inode and dentry. 416 + 417 + rename2: this has an additional flags argument compared to rename. 418 + If no flags are supported by the filesystem then this method 419 + need not be implemented. If some flags are supported then the 420 + filesystem must return -EINVAL for any unsupported or unknown 421 + flags. Currently the following flags are implemented: 422 + (1) RENAME_NOREPLACE: this flag indicates that if the target 423 + of the rename exists the rename should fail with -EEXIST 424 + instead of replacing the target. The VFS already checks for 425 + existence, so for local filesystems the RENAME_NOREPLACE 426 + implementation is equivalent to plain rename. 427 + (2) RENAME_EXCHANGE: exchange source and target. Both must 428 + exist; this is checked by the VFS. Unlike plain rename, 429 + source and target may be of different type. 418 430 419 431 readlink: called by the readlink(2) system call. Only required if 420 432 you want to support reading symbolic links
+1
arch/x86/syscalls/syscall_64.tbl
··· 322 322 313 common finit_module sys_finit_module 323 323 314 common sched_setattr sys_sched_setattr 324 324 315 common sched_getattr sys_sched_getattr 325 + 316 common renameat2 sys_renameat2 325 326 326 327 # 327 328 # x32-specific system call numbers start at 512 to avoid cache impact
+2 -2
drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
··· 105 105 #define ll_vfs_unlink(inode,entry,mnt) vfs_unlink(inode,entry) 106 106 #define ll_vfs_mknod(dir,entry,mnt,mode,dev) vfs_mknod(dir,entry,mode,dev) 107 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) \ 109 - vfs_rename(old,old_dir,new,new_dir,delegated_inode) 108 + #define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \ 109 + vfs_rename(old, old_dir, new, new_dir, NULL, 0) 110 110 111 111 #define cfs_bio_io_error(a,b) bio_io_error((a)) 112 112 #define cfs_bio_endio(a,b,c) bio_endio((a),(c))
+1 -1
drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
··· 223 223 GOTO(put_old, err = PTR_ERR(dchild_new)); 224 224 225 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 228 dput(dchild_new); 229 229 put_old:
+1 -1
fs/cachefiles/namei.c
··· 396 396 cachefiles_io_error(cache, "Rename security error %d", ret); 397 397 } else { 398 398 ret = vfs_rename(dir->d_inode, rep, 399 - cache->graveyard->d_inode, grave, NULL); 399 + cache->graveyard->d_inode, grave, NULL, 0); 400 400 if (ret != 0 && ret != -ENOMEM) 401 401 cachefiles_io_error(cache, 402 402 "Rename failed with error %d", ret);
+1 -1
fs/ecryptfs/inode.c
··· 641 641 } 642 642 rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, 643 643 lower_new_dir_dentry->d_inode, lower_new_dentry, 644 - NULL); 644 + NULL, 0); 645 645 if (rc) 646 646 goto out_lock; 647 647 if (target_inode)
+27 -7
fs/namei.c
··· 3980 3980 * @new_dir: parent of destination 3981 3981 * @new_dentry: destination 3982 3982 * @delegated_inode: returns an inode needing a delegation break 3983 + * @flags: rename flags 3983 3984 * 3984 3985 * The caller must hold multiple mutexes--see lock_rename()). 3985 3986 * ··· 4024 4023 */ 4025 4024 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 4026 4025 struct inode *new_dir, struct dentry *new_dentry, 4027 - struct inode **delegated_inode) 4026 + struct inode **delegated_inode, unsigned int flags) 4028 4027 { 4029 4028 int error; 4030 4029 bool is_dir = d_is_dir(old_dentry); ··· 4048 4047 4049 4048 if (!old_dir->i_op->rename) 4050 4049 return -EPERM; 4050 + 4051 + if (flags && !old_dir->i_op->rename2) 4052 + return -EINVAL; 4051 4053 4052 4054 /* 4053 4055 * If we are going to change the parent - check write permissions, ··· 4097 4093 goto out; 4098 4094 } 4099 4095 } 4100 - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); 4096 + if (!flags) { 4097 + error = old_dir->i_op->rename(old_dir, old_dentry, 4098 + new_dir, new_dentry); 4099 + } else { 4100 + error = old_dir->i_op->rename2(old_dir, old_dentry, 4101 + new_dir, new_dentry, flags); 4102 + } 4101 4103 if (error) 4102 4104 goto out; 4103 4105 ··· 4128 4118 return error; 4129 4119 } 4130 4120 4131 - SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, 4132 - int, newdfd, const char __user *, newname) 4121 + SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, 4122 + int, newdfd, const char __user *, newname, unsigned int, flags) 4133 4123 { 4134 4124 struct dentry *old_dir, *new_dir; 4135 4125 struct dentry *old_dentry, *new_dentry; ··· 4141 4131 unsigned int lookup_flags = 0; 4142 4132 bool should_retry = false; 4143 4133 int error; 4134 + 4135 + if (flags) 4136 + return -EINVAL; 4137 + 4144 4138 retry: 4145 4139 from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); 4146 4140 if (IS_ERR(from)) { ··· 4216 4202 if (error) 4217 4203 goto exit5; 4218 4204 error = vfs_rename(old_dir->d_inode, old_dentry, 4219 - new_dir->d_inode, new_dentry, 4220 - &delegated_inode); 4205 + new_dir->d_inode, new_dentry, 4206 + &delegated_inode, flags); 4221 4207 exit5: 4222 4208 dput(new_dentry); 4223 4209 exit4: ··· 4247 4233 return error; 4248 4234 } 4249 4235 4236 + SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, 4237 + int, newdfd, const char __user *, newname) 4238 + { 4239 + return sys_renameat2(olddfd, oldname, newdfd, newname, 0); 4240 + } 4241 + 4250 4242 SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) 4251 4243 { 4252 - return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); 4244 + return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); 4253 4245 } 4254 4246 4255 4247 int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
+1 -1
fs/nfsd/vfs.c
··· 1694 1694 if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) 1695 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 1698 if (!host_err) { 1699 1699 host_err = commit_metadata(tfhp); 1700 1700 if (!host_err)
+3 -1
include/linux/fs.h
··· 1460 1460 extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); 1461 1461 extern int vfs_rmdir(struct inode *, struct dentry *); 1462 1462 extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); 1463 - extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **); 1463 + extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); 1464 1464 1465 1465 /* 1466 1466 * VFS dentry helper functions. ··· 1571 1571 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 1572 1572 int (*rename) (struct inode *, struct dentry *, 1573 1573 struct inode *, struct dentry *); 1574 + int (*rename2) (struct inode *, struct dentry *, 1575 + struct inode *, struct dentry *, unsigned int); 1574 1576 int (*setattr) (struct dentry *, struct iattr *); 1575 1577 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1576 1578 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);