Merge pull request #25 from giuseppe/fix-wh-variant

fuse-overlayfs: fix a couple of issues with the .wh. variant and enable tests
This commit is contained in:
Giuseppe Scrivano 2018-11-07 14:02:46 +01:00 committed by GitHub
commit 3d48bf9a82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 16 deletions

View File

@ -27,3 +27,4 @@ script:
- make -j $(nproc) - make -j $(nproc)
- sudo make -j install; sudo cp fuse-overlayfs /sbin - sudo make -j install; sudo cp fuse-overlayfs /sbin
- (cd /unionmount-testsuite; sudo ./run --ov --fuse=fuse-overlayfs --xdev) - (cd /unionmount-testsuite; sudo ./run --ov --fuse=fuse-overlayfs --xdev)
- (cd /unionmount-testsuite; FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 sudo -E ./run --ov --fuse=fuse-overlayfs --xdev)

74
main.c
View File

@ -83,6 +83,8 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct
}; };
#endif #endif
static bool disable_ovl_whiteout;
struct ovl_layer struct ovl_layer
{ {
struct ovl_layer *next; struct ovl_layer *next;
@ -374,7 +376,7 @@ create_whiteout (struct ovl_data *lo, struct ovl_node *parent, const char *name,
int fd = -1; int fd = -1;
static bool can_mknod = true; static bool can_mknod = true;
if (!skip_mknod && can_mknod) if (!disable_ovl_whiteout && !skip_mknod && can_mknod)
{ {
int ret; int ret;
@ -881,7 +883,7 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
{ {
DIR *dp; DIR *dp;
struct dirent *dent; struct dirent *dent;
struct stat st; struct stat st, tmp_st;
struct ovl_layer *it, *upper_layer = get_upper_layer (lo); struct ovl_layer *it, *upper_layer = get_upper_layer (lo);
if (!n) if (!n)
@ -906,6 +908,7 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
for (;;) for (;;)
{ {
int ret;
struct ovl_node key; struct ovl_node key;
const char *wh; const char *wh;
struct ovl_node *child = NULL; struct ovl_node *child = NULL;
@ -954,12 +957,18 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
} }
} }
sprintf (node_path, ".wh.%s", dent->d_name);
ret = TEMP_FAILURE_RETRY (fstatat (fd, node_path, &tmp_st, AT_SYMLINK_NOFOLLOW));
if (ret < 0 && errno != ENOENT)
{
closedir (dp);
return NULL;
}
sprintf (node_path, "%s/%s", n->path, dent->d_name); sprintf (node_path, "%s/%s", n->path, dent->d_name);
wh = get_whiteout_name (dent->d_name, &st); if (ret == 0)
if (wh)
{ {
child = make_whiteout_node (node_path, wh); child = make_whiteout_node (node_path, dent->d_name);
if (child == NULL) if (child == NULL)
{ {
errno = ENOMEM; errno = ENOMEM;
@ -969,14 +978,28 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
} }
else else
{ {
bool dirp = st.st_mode & S_IFDIR; wh = get_whiteout_name (dent->d_name, &st);
if (wh)
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n);
if (child == NULL)
{ {
errno = ENOMEM; child = make_whiteout_node (node_path, wh);
closedir (dp); if (child == NULL)
return NULL; {
errno = ENOMEM;
closedir (dp);
return NULL;
}
}
else
{
bool dirp = st.st_mode & S_IFDIR;
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n);
if (child == NULL)
{
errno = ENOMEM;
closedir (dp);
return NULL;
}
} }
} }
@ -1106,7 +1129,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
char path[PATH_MAX]; char path[PATH_MAX];
char whpath[PATH_MAX]; char whpath[PATH_MAX];
struct ovl_layer *it; struct ovl_layer *it;
struct stat st; struct stat st, tmp_st;
struct ovl_layer *upper_layer = get_upper_layer (lo); struct ovl_layer *upper_layer = get_upper_layer (lo);
for (it = lo->layers; it; it = it->next) for (it = lo->layers; it; it = it->next)
@ -1120,7 +1143,23 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
int saved_errno = errno; int saved_errno = errno;
if (errno == ENOENT) if (errno == ENOENT)
continue; {
sprintf (whpath, "%s/.wh.%s", pnode->path, name);
ret = TEMP_FAILURE_RETRY (fstatat (it->fd, whpath, &tmp_st, AT_SYMLINK_NOFOLLOW));
if (ret < 0 && errno != ENOENT)
return NULL;
if (ret == 0)
{
node = make_whiteout_node (path, name);
if (node == NULL)
{
errno = ENOMEM;
return NULL;
}
goto insert_node;
}
continue;
}
if (node) if (node)
node_free (node); node_free (node);
@ -1148,7 +1187,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
} }
sprintf (whpath, "%s/.wh.%s", pnode->path, name); sprintf (whpath, "%s/.wh.%s", pnode->path, name);
ret = TEMP_FAILURE_RETRY (fstatat (it->fd, whpath, &st, AT_SYMLINK_NOFOLLOW)); ret = TEMP_FAILURE_RETRY (fstatat (it->fd, whpath, &tmp_st, AT_SYMLINK_NOFOLLOW));
if (ret < 0 && errno != ENOENT) if (ret < 0 && errno != ENOENT)
return NULL; return NULL;
if (ret == 0) if (ret == 0)
@ -1178,7 +1217,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
if (ret > 0) if (ret > 0)
node->last_layer = it; node->last_layer = it;
} }
insert_node:
if (insert_node (pnode, node, false) == NULL) if (insert_node (pnode, node, false) == NULL)
{ {
node_free (node); node_free (node);
@ -3541,6 +3580,9 @@ main (int argc, char *argv[])
int ret = -1; int ret = -1;
struct fuse_args args = FUSE_ARGS_INIT (argc, newargv); struct fuse_args args = FUSE_ARGS_INIT (argc, newargv);
if (getenv ("FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT"))
disable_ovl_whiteout = true;
memset (&opts, 0, sizeof (opts)); memset (&opts, 0, sizeof (opts));
if (fuse_opt_parse (&args, &lo, ovl_opts, fuse_opt_proc) == -1) if (fuse_opt_parse (&args, &lo, ovl_opts, fuse_opt_proc) == -1)
error (EXIT_FAILURE, 0, "error parsing options"); error (EXIT_FAILURE, 0, "error parsing options");