aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/namei.c11
-rw-r--r--fs/namei.c21
-rw-r--r--include/uapi/linux/fs.h2
3 files changed, 26 insertions, 8 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index d050e043e884..5f19171b3e1f 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3204,6 +3204,16 @@ end_rename:
3204 return retval; 3204 return retval;
3205} 3205}
3206 3206
3207static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry,
3208 struct inode *new_dir, struct dentry *new_dentry,
3209 unsigned int flags)
3210{
3211 if (flags & ~RENAME_NOREPLACE)
3212 return -EINVAL;
3213
3214 return ext4_rename(old_dir, old_dentry, new_dir, new_dentry);
3215}
3216
3207/* 3217/*
3208 * directories can handle most operations... 3218 * directories can handle most operations...
3209 */ 3219 */
@@ -3218,6 +3228,7 @@ const struct inode_operations ext4_dir_inode_operations = {
3218 .mknod = ext4_mknod, 3228 .mknod = ext4_mknod,
3219 .tmpfile = ext4_tmpfile, 3229 .tmpfile = ext4_tmpfile,
3220 .rename = ext4_rename, 3230 .rename = ext4_rename,
3231 .rename2 = ext4_rename2,
3221 .setattr = ext4_setattr, 3232 .setattr = ext4_setattr,
3222 .setxattr = generic_setxattr, 3233 .setxattr = generic_setxattr,
3223 .getxattr = generic_getxattr, 3234 .getxattr = generic_getxattr,
diff --git a/fs/namei.c b/fs/namei.c
index ab4e48c4a80a..0e9d186b7f77 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4142,7 +4142,7 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
4142 bool should_retry = false; 4142 bool should_retry = false;
4143 int error; 4143 int error;
4144 4144
4145 if (flags) 4145 if (flags & ~RENAME_NOREPLACE)
4146 return -EINVAL; 4146 return -EINVAL;
4147 4147
4148retry: 4148retry:
@@ -4168,6 +4168,8 @@ retry:
4168 goto exit2; 4168 goto exit2;
4169 4169
4170 new_dir = newnd.path.dentry; 4170 new_dir = newnd.path.dentry;
4171 if (flags & RENAME_NOREPLACE)
4172 error = -EEXIST;
4171 if (newnd.last_type != LAST_NORM) 4173 if (newnd.last_type != LAST_NORM)
4172 goto exit2; 4174 goto exit2;
4173 4175
@@ -4190,22 +4192,25 @@ retry_deleg:
4190 error = -ENOENT; 4192 error = -ENOENT;
4191 if (d_is_negative(old_dentry)) 4193 if (d_is_negative(old_dentry))
4192 goto exit4; 4194 goto exit4;
4195 new_dentry = lookup_hash(&newnd);
4196 error = PTR_ERR(new_dentry);
4197 if (IS_ERR(new_dentry))
4198 goto exit4;
4199 error = -EEXIST;
4200 if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry))
4201 goto exit5;
4193 /* unless the source is a directory trailing slashes give -ENOTDIR */ 4202 /* unless the source is a directory trailing slashes give -ENOTDIR */
4194 if (!d_is_dir(old_dentry)) { 4203 if (!d_is_dir(old_dentry)) {
4195 error = -ENOTDIR; 4204 error = -ENOTDIR;
4196 if (oldnd.last.name[oldnd.last.len]) 4205 if (oldnd.last.name[oldnd.last.len])
4197 goto exit4; 4206 goto exit5;
4198 if (newnd.last.name[newnd.last.len]) 4207 if (newnd.last.name[newnd.last.len])
4199 goto exit4; 4208 goto exit5;
4200 } 4209 }
4201 /* source should not be ancestor of target */ 4210 /* source should not be ancestor of target */
4202 error = -EINVAL; 4211 error = -EINVAL;
4203 if (old_dentry == trap) 4212 if (old_dentry == trap)
4204 goto exit4; 4213 goto exit5;
4205 new_dentry = lookup_hash(&newnd);
4206 error = PTR_ERR(new_dentry);
4207 if (IS_ERR(new_dentry))
4208 goto exit4;
4209 /* target should not be an ancestor of source */ 4214 /* target should not be an ancestor of source */
4210 error = -ENOTEMPTY; 4215 error = -ENOTEMPTY;
4211 if (new_dentry == trap) 4216 if (new_dentry == trap)
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 6c28b61bb690..9250f4dd7d96 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -35,6 +35,8 @@
35#define SEEK_HOLE 4 /* seek to the next hole */ 35#define SEEK_HOLE 4 /* seek to the next hole */
36#define SEEK_MAX SEEK_HOLE 36#define SEEK_MAX SEEK_HOLE
37 37
38#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
39
38struct fstrim_range { 40struct fstrim_range {
39 __u64 start; 41 __u64 start;
40 __u64 len; 42 __u64 len;