Skip to content

Commit 6221ded

Browse files
authored
Merge pull request #357 from Tuupertunut/main
Refactor and fix rename code
2 parents 918e19c + 6a0de4a commit 6221ded

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

main.c

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4541,11 +4541,15 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
45414541
if (node == NULL)
45424542
goto error;
45434543

4544+
/* If NOREPLACE flag is given, check if we should throw an error now.
4545+
If not, just remove the flag as it might cause problems with replacing whiteouts later. */
45444546
if (flags & RENAME_NOREPLACE && destnode && !destnode->whiteout)
45454547
{
45464548
errno = EEXIST;
45474549
goto error;
45484550
}
4551+
else
4552+
flags = flags & ~RENAME_NOREPLACE;
45494553

45504554
if (destnode)
45514555
{
@@ -4600,17 +4604,6 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
46004604
}
46014605
}
46024606

4603-
/* If the destnode is a whiteout, first attempt to EXCHANGE the source and the destination,
4604-
so that with one operation we get both the rename and the whiteout created. */
4605-
if (destnode_is_whiteout)
4606-
{
4607-
ret = direct_renameat2 (srcfd, name, destfd, newname, flags|RENAME_EXCHANGE);
4608-
if (ret == 0)
4609-
goto done;
4610-
4611-
/* If it fails for any reason, fallback to the more articulated method. */
4612-
}
4613-
46144607
/* If the node is a directory we must ensure there is no whiteout at the
46154608
destination, otherwise the renameat2 will fail. Create a .wh.$NAME style
46164609
whiteout file until the renameat2 is completed. */
@@ -4622,39 +4615,51 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
46224615
unlinkat (destfd, newname, 0);
46234616
}
46244617

4625-
/* Try to create the whiteout atomically, if it fails do the
4626-
rename+mknod separately. */
4627-
if (! can_mknod)
4618+
bool src_needs_whiteout = (node->last_layer != get_upper_layer (lo));
4619+
4620+
if (src_needs_whiteout)
46284621
{
4629-
ret = -1;
4630-
errno = EPERM;
4622+
/* Trying to atomically both rename and create the whiteout.
4623+
If destination is a whiteout, we can EXCHANGE source and destination and reuse the old whiteout.
4624+
If not, we can try to atomically create one with the WHITEOUT flag. */
4625+
if (destnode_is_whiteout)
4626+
ret = direct_renameat2 (srcfd, name, destfd, newname, flags|RENAME_EXCHANGE);
4627+
else
4628+
{
4629+
if (! can_mknod)
4630+
{
4631+
ret = -1;
4632+
errno = EPERM;
4633+
}
4634+
else
4635+
ret = direct_renameat2 (srcfd, name, destfd, newname, flags|RENAME_WHITEOUT);
4636+
}
4637+
4638+
/* If atomic whiteout creation failed, fall back to separate rename and whiteout creation. */
4639+
if (ret < 0)
4640+
{
4641+
ret = direct_renameat2 (srcfd, name, destfd, newname, flags);
4642+
if (ret < 0)
4643+
goto error;
4644+
4645+
ret = create_whiteout (lo, pnode, name, false, true);
4646+
if (ret < 0)
4647+
goto error;
4648+
}
46314649
}
46324650
else
46334651
{
4634-
ret = direct_renameat2 (srcfd, name, destfd,
4635-
newname, flags|RENAME_WHITEOUT);
4636-
}
4637-
/* If the destination is a whiteout, just overwrite it. */
4638-
if (ret < 0 && errno == EEXIST)
4639-
ret = direct_renameat2 (srcfd, name, destfd, newname, flags & ~RENAME_NOREPLACE);
4640-
if (ret < 0)
4641-
{
4642-
ret = direct_renameat2 (srcfd, name, destfd,
4643-
newname, flags);
4652+
ret = direct_renameat2 (srcfd, name, destfd, newname, flags);
46444653
if (ret < 0)
46454654
goto error;
4646-
4647-
ret = create_whiteout (lo, pnode, name, false, true);
4648-
if (ret < 0)
4649-
goto error;
4650-
4651-
pnode->loaded = 0;
46524655
}
46534656

4657+
pnode->loaded = 0;
4658+
4659+
/* If the destination was .wh. style whiteout, it was not replaced automatically, so delete it. */
46544660
if (delete_whiteout (lo, destfd, NULL, newname) < 0)
46554661
goto error;
46564662

4657-
done:
46584663
hash_delete (pnode->children, node);
46594664

46604665
free (node->name);

0 commit comments

Comments
 (0)