containerfs: simplify hide_node

use a hard link so we don't modify the destination file before a
rename(2).

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2018-06-30 10:59:27 +02:00
parent f2b97eeea5
commit f131a755fa
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED

59
main.c
View File

@ -245,34 +245,42 @@ get_node_path (struct lo_node *node)
}
static int
hide_node (struct lo_data *lo, struct lo_node *node)
hide_node (struct lo_data *lo, struct lo_node *node, bool unlink_src)
{
char dest[PATH_MAX];
char *newpath;
int ret;
static unsigned long counter = 1;
node->hidden = 1;
node->parent = NULL;
sprintf (dest, "%s/tmp-XXXXXX", lo->workdir);
ret = mkstemp (dest);
if (ret < 0)
return ret;
close (ret);
newpath = strdup (dest);
asprintf (&newpath, "%s/%lu", lo->workdir, counter++);
if (newpath == NULL)
{
unlink (dest);
return -1;
}
if (rename (node->path, newpath) < 0)
/* Might be leftover from a previous run. */
unlink (newpath);
if (unlink_src)
{
free (newpath);
unlink (dest);
return -1;
if (rename (node->path, newpath) < 0)
{
free (newpath);
return -1;
}
}
else
{
if (link (node->path, newpath) < 0)
{
free (newpath);
return -1;
}
}
free (node->path);
node->path = newpath;
@ -1733,7 +1741,7 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
rm = hash_delete (pnode->children, &key);
if (rm)
{
hide_node (lo, rm);
hide_node (lo, rm, true);
node_free (rm);
}
@ -2360,22 +2368,6 @@ lo_flock (fuse_req_t req, fuse_ino_t ino,
fuse_reply_err (req, ret == 0 ? 0 : errno);
}
/* used to recover a failed lo_rename. */
static struct lo_node *
unhide_node (struct lo_node *node, struct lo_node *parent)
{
char b[PATH_MAX];
if (node->path == NULL)
return node;
sprintf (b, "%s/%s", parent->path, node->name);
rename (node->path, b);
free (node->path);
node->path = strdup (b);
return insert_node (parent, node, true);
}
static struct lo_node *
get_node_up_rec (struct lo_data *lo, struct lo_node *node)
{
@ -2503,7 +2495,7 @@ lo_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
rm = NULL;
}
if (rm && !rm->not_exists && hide_node (lo, rm) < 0)
if (rm && !rm->not_exists && hide_node (lo, rm, false) < 0)
goto error;
}
}
@ -2511,9 +2503,6 @@ lo_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
ret = syscall (SYS_renameat2, srcfd, name, destfd, newname, flags);
if (ret < 0)
{
if (rm)
destpnode = unhide_node (rm, destpnode);
pnode->dirty = destpnode->dirty = 1;
goto error;
}