aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Xiaoxu <[email protected]>2020-06-28 21:06:38 -0400
committerSteve French <[email protected]>2020-07-01 19:41:56 -0500
commit9ffad9263b467efd8f8dc7ae1941a0a655a2bab2 (patch)
treec0cfe2bdb4dc73cd6d0f77c5894130bf4c2a280c
parent5391b8e1b7b7e5cfa2dd4ffdc4b8c6b64dfd1866 (diff)
cifs: Fix the target file was deleted when rename failed.
When xfstest generic/035, we found the target file was deleted if the rename return -EACESS. In cifs_rename2, we unlink the positive target dentry if rename failed with EACESS or EEXIST, even if the target dentry is positived before rename. Then the existing file was deleted. We should just delete the target file which created during the rename. Reported-by: Hulk Robot <[email protected]> Signed-off-by: Zhang Xiaoxu <[email protected]> Cc: [email protected] Signed-off-by: Steve French <[email protected]> Reviewed-by: Aurelien Aptel <[email protected]>
-rw-r--r--fs/cifs/inode.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ce95801e9b66..49c3ea8aa845 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2044,6 +2044,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
FILE_UNIX_BASIC_INFO *info_buf_target;
unsigned int xid;
int rc, tmprc;
+ bool new_target = d_really_is_negative(target_dentry);
if (flags & ~RENAME_NOREPLACE)
return -EINVAL;
@@ -2120,8 +2121,13 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
*/
unlink_target:
- /* Try unlinking the target dentry if it's not negative */
- if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
+ /*
+ * If the target dentry was created during the rename, try
+ * unlinking it if it's not negative
+ */
+ if (new_target &&
+ d_really_is_positive(target_dentry) &&
+ (rc == -EACCES || rc == -EEXIST)) {
if (d_is_dir(target_dentry))
tmprc = cifs_rmdir(target_dir, target_dentry);
else