Commit 520c8b16505236fc82daa352e6c5e73cd9870cff

Authored by Miklos Szeredi
1 parent bc27027a73

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>

Showing 10 changed files with 58 additions and 15 deletions Side-by-side Diff

Documentation/filesystems/Locking
... ... @@ -47,6 +47,8 @@
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 *);
... ... @@ -78,6 +80,7 @@
78 80 unlink: yes (both)
79 81 rmdir: yes (both) (see below)
80 82 rename: yes (all) (see below)
  83 +rename2: yes (all) (see below)
81 84 readlink: no
82 85 follow_link: no
83 86 put_link: no
... ... @@ -96,7 +99,8 @@
96 99  
97 100 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
98 101 victim.
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  
101 105 See Documentation/filesystems/directory-locking for more detailed discussion
102 106 of the locking scheme for directory operations.
Documentation/filesystems/vfs.txt
... ... @@ -347,6 +347,8 @@
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 *);
... ... @@ -413,6 +415,20 @@
413 415  
414 416 rename: called by the rename(2) system call to rename the object to
415 417 have the parent and name given by the second inode and dentry.
  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.
416 432  
417 433 readlink: called by the readlink(2) system call. Only required if
418 434 you want to support reading symbolic links
arch/x86/syscalls/syscall_64.tbl
... ... @@ -322,6 +322,7 @@
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
drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
... ... @@ -105,8 +105,8 @@
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))
drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
... ... @@ -223,7 +223,7 @@
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:
fs/cachefiles/namei.c
... ... @@ -396,7 +396,7 @@
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);
... ... @@ -641,7 +641,7 @@
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)
... ... @@ -3980,6 +3980,7 @@
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 *
... ... @@ -4023,7 +4024,7 @@
4023 4024 */
4024 4025 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
4025 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 4029 int error;
4029 4030 bool is_dir = d_is_dir(old_dentry);
... ... @@ -4048,6 +4049,9 @@
4048 4049 if (!old_dir->i_op->rename)
4049 4050 return -EPERM;
4050 4051  
  4052 + if (flags && !old_dir->i_op->rename2)
  4053 + return -EINVAL;
  4054 +
4051 4055 /*
4052 4056 * If we are going to change the parent - check write permissions,
4053 4057 * we'll need to flip '..'.
... ... @@ -4093,7 +4097,13 @@
4093 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 4107 if (error)
4098 4108 goto out;
4099 4109  
... ... @@ -4118,8 +4128,8 @@
4118 4128 return error;
4119 4129 }
4120 4130  
4121   -SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
4122   - int, newdfd, const char __user *, newname)
  4131 +SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
  4132 + int, newdfd, const char __user *, newname, unsigned int, flags)
4123 4133 {
4124 4134 struct dentry *old_dir, *new_dir;
4125 4135 struct dentry *old_dentry, *new_dentry;
... ... @@ -4131,6 +4141,10 @@
4131 4141 unsigned int lookup_flags = 0;
4132 4142 bool should_retry = false;
4133 4143 int error;
  4144 +
  4145 + if (flags)
  4146 + return -EINVAL;
  4147 +
4134 4148 retry:
4135 4149 from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
4136 4150 if (IS_ERR(from)) {
... ... @@ -4202,8 +4216,8 @@
4202 4216 if (error)
4203 4217 goto exit5;
4204 4218 error = vfs_rename(old_dir->d_inode, old_dentry,
4205   - new_dir->d_inode, new_dentry,
4206   - &delegated_inode);
  4219 + new_dir->d_inode, new_dentry,
  4220 + &delegated_inode, flags);
4207 4221 exit5:
4208 4222 dput(new_dentry);
4209 4223 exit4:
4210 4224  
... ... @@ -4233,9 +4247,15 @@
4233 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 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 4261 int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
... ... @@ -1694,7 +1694,7 @@
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)
... ... @@ -1460,7 +1460,7 @@
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,6 +1571,8 @@
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);