fuse-overlayfs: split ovl_rename in two functions

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2018-07-15 14:30:26 +02:00
parent 234a1baaf9
commit b3f454183f
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED

184
main.c
View File

@ -2560,7 +2560,7 @@ ovl_flock (fuse_req_t req, fuse_ino_t ino,
}
static void
ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_ino_t newparent, const char *newname,
unsigned int flags)
{
@ -2570,10 +2570,8 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
int saved_errno;
int srcfd = -1;
int destfd = -1;
struct ovl_node key, *rm = NULL;
if (ovl_debug (req))
fprintf (stderr, "ovl_rename(ino=%" PRIu64 "s, name=%s , ino=%" PRIu64 "s, name=%s)\n", parent, name, newparent, newname);
struct ovl_node *rm1, *rm2;
char *tmp;
node = do_lookup_file (lo, parent, name);
if (node == NULL)
@ -2626,8 +2624,6 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
if (node == NULL)
goto error;
if (flags & RENAME_EXCHANGE)
{
if (destnode == NULL)
{
errno = ENOENT;
@ -2641,9 +2637,124 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
destnode = get_node_up (lo, destnode);
if (destnode == NULL)
goto error;
}
else
ret = syscall (SYS_renameat2, srcfd, name, destfd, newname, flags);
if (ret < 0)
goto error;
rm1 = hash_delete (destpnode->children, destnode);
rm2 = hash_delete (pnode->children, node);
tmp = node->path;
node->path = destnode->path;
destnode->path = tmp;
tmp = node->name;
node->name = destnode->name;
destnode->name = tmp;
node = insert_node (destpnode, node, true);
if (node == NULL)
{
node_free (rm1);
node_free (rm2);
goto error;
}
destnode = insert_node (pnode, destnode, true);
if (destnode == NULL)
{
node_free (rm1);
node_free (rm2);
goto error;
}
if ((update_paths (node) < 0) || (update_paths (destnode) < 0))
goto error;
if (delete_whiteout (lo, destfd, NULL, newname) < 0)
goto error;
ret = 0;
goto cleanup;
error:
ret = -1;
cleanup:
saved_errno = errno;
if (srcfd >= 0)
close (srcfd);
if (destfd >= 0)
close (destfd);
errno = saved_errno;
fuse_reply_err (req, ret == 0 ? 0 : errno);
}
static void
ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_ino_t newparent, const char *newname,
unsigned int flags)
{
struct ovl_node *pnode, *node, *destnode, *destpnode;
struct ovl_data *lo = ovl_data (req);
int ret;
int saved_errno;
int srcfd = -1;
int destfd = -1;
struct ovl_node key, *rm = NULL;
node = do_lookup_file (lo, parent, name);
if (node == NULL)
{
fuse_reply_err (req, ENOENT);
return;
}
if (node_dirp (node))
{
node = load_dir (lo, node, node->layer, node->path, node->name);
if (node == NULL)
{
fuse_reply_err (req, errno);
return;
}
if (node->layer != get_upper_layer (lo) || node->present_lowerdir)
{
fuse_reply_err (req, EXDEV);
return;
}
}
pnode = node->parent;
destpnode = do_lookup_file (lo, newparent, NULL);
destnode = NULL;
pnode = get_node_up (lo, pnode);
if (pnode == NULL)
goto error;
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (pnode), pnode->path, O_DIRECTORY));
if (ret < 0)
goto error;
srcfd = ret;
destpnode = get_node_up (lo, destpnode);
if (destpnode == NULL)
goto error;
ret = TEMP_FAILURE_RETRY (openat (node_dirfd (destpnode), destpnode->path, O_DIRECTORY));
if (ret < 0)
goto error;
destfd = ret;
destnode = do_lookup_file (lo, newparent, newname);
node = get_node_up (lo, node);
if (node == NULL)
goto error;
key.name = (char *) newname;
if (flags & RENAME_NOREPLACE)
{
@ -2716,47 +2827,7 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
goto error;
}
}
}
if (flags & RENAME_EXCHANGE)
{
struct ovl_node *rm1, *rm2;
char *tmp;
ret = syscall (SYS_renameat2, srcfd, name, destfd, newname, flags);
if (ret < 0)
goto error;
rm1 = hash_delete (destpnode->children, destnode);
rm2 = hash_delete (pnode->children, node);
tmp = node->path;
node->path = destnode->path;
destnode->path = tmp;
tmp = node->name;
node->name = destnode->name;
destnode->name = tmp;
node = insert_node (destpnode, node, true);
if (node == NULL)
{
node_free (rm1);
node_free (rm2);
goto error;
}
destnode = insert_node (pnode, destnode, true);
if (destnode == NULL)
{
node_free (rm1);
node_free (rm2);
goto error;
}
if ((update_paths (node) < 0) || (update_paths (destnode) < 0))
goto error;
}
else
{
unlinkat (destfd, newname, 0);
/* Try to create the whiteout atomically, if it fails do the
@ -2789,7 +2860,6 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
goto error;
if (update_paths (node) < 0)
goto error;
}
if (delete_whiteout (lo, destfd, NULL, newname) < 0)
goto error;
@ -2811,6 +2881,20 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_reply_err (req, ret == 0 ? 0 : errno);
}
static void
ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_ino_t newparent, const char *newname,
unsigned int flags)
{
if (ovl_debug (req))
fprintf (stderr, "ovl_rename(ino=%" PRIu64 "s, name=%s , ino=%" PRIu64 "s, name=%s)\n", parent, name, newparent, newname);
if (flags & RENAME_EXCHANGE)
ovl_rename_exchange (req, parent, name, newparent, newname, flags);
else
ovl_rename_direct (req, parent, name, newparent, newname, flags);
}
static void
ovl_statfs (fuse_req_t req, fuse_ino_t ino)
{