diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-10-23 18:14:37 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-10-23 18:14:37 -0400 |
commit | 0d7a855526dd672e114aff2ac22b60fc6f155b08 (patch) | |
tree | 5354ed84bddf7ca55c6cdd3509a71fd8e0bcf63e | |
parent | 787fb6bc9682ec7c05fb5d9561b57100fbc1cc41 (diff) |
vfs: add RENAME_WHITEOUT
This adds a new RENAME_WHITEOUT flag. This flag makes rename() create a
whiteout of source. The whiteout creation is atomic relative to the
rename.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r-- | fs/namei.c | 8 | ||||
-rw-r--r-- | include/uapi/linux/fs.h | 1 |
2 files changed, 7 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c index d20191c0ebf5..42df664e95e5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -4209,12 +4209,16 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, | |||
4209 | bool should_retry = false; | 4209 | bool should_retry = false; |
4210 | int error; | 4210 | int error; |
4211 | 4211 | ||
4212 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | 4212 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) |
4213 | return -EINVAL; | 4213 | return -EINVAL; |
4214 | 4214 | ||
4215 | if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE)) | 4215 | if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) && |
4216 | (flags & RENAME_EXCHANGE)) | ||
4216 | return -EINVAL; | 4217 | return -EINVAL; |
4217 | 4218 | ||
4219 | if ((flags & RENAME_WHITEOUT) && !capable(CAP_MKNOD)) | ||
4220 | return -EPERM; | ||
4221 | |||
4218 | retry: | 4222 | retry: |
4219 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); | 4223 | from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags); |
4220 | if (IS_ERR(from)) { | 4224 | if (IS_ERR(from)) { |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index ca1a11bb4443..3735fa0a6784 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */ | 38 | #define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */ |
39 | #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */ | 39 | #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */ |
40 | #define RENAME_WHITEOUT (1 << 2) /* Whiteout source */ | ||
40 | 41 | ||
41 | struct fstrim_range { | 42 | struct fstrim_range { |
42 | __u64 start; | 43 | __u64 start; |