From bb1890afd7d1eb33e95f36d1d9936dbd574260b6 Mon Sep 17 00:00:00 2001 From: Peri Date: Thu, 11 May 2023 02:38:46 +0100 Subject: Fix issue #746. (#782) Added a secondary check in fuse_lib_unlink() after hide_node() to check again under a lock if the (now hidden) file is still open. If not then delete it. This should synchronise fuse_lib_unlink() with fuse_lib_release(), when nullpath_ok is set. --- test/release_unlink_race.c | 111 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 test/release_unlink_race.c (limited to 'test/release_unlink_race.c') diff --git a/test/release_unlink_race.c b/test/release_unlink_race.c new file mode 100644 index 0000000..2edb200 --- /dev/null +++ b/test/release_unlink_race.c @@ -0,0 +1,111 @@ +/* + This program can be distributed under the terms of the GNU GPLv2. + See the file COPYING. +*/ + +#define FUSE_USE_VERSION 31 + +#define _GNU_SOURCE + +#include + +#include +#include +#include +#include + +static void *xmp_init(struct fuse_conn_info *conn, + struct fuse_config *cfg) +{ + (void) conn; + + cfg->use_ino = 1; + cfg->nullpath_ok = 1; + cfg->entry_timeout = 0; + cfg->attr_timeout = 0; + cfg->negative_timeout = 0; + + return NULL; +} + +static int xmp_getattr(const char *path, struct stat *stbuf, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + if(fi) + res = fstat(fi->fh, stbuf); + else + res = lstat(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_unlink(const char *path) +{ + int res; + + res = unlink(path); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_rename(const char *from, const char *to, unsigned int flags) +{ + int res; + + if (flags) + return -EINVAL; + + if(!getenv("RELEASEUNLINKRACE_DELAY_DISABLE")) usleep(100000); + + res = rename(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int fd; + + fd = open(path, fi->flags, mode); + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int xmp_release(const char *path, struct fuse_file_info *fi) +{ + (void) path; + + if(!getenv("RELEASEUNLINKRACE_DELAY_DISABLE")) usleep(100000); + + close(fi->fh); + + return 0; +} + +static const struct fuse_operations xmp_oper = { + .init = xmp_init, + .getattr = xmp_getattr, + .unlink = xmp_unlink, + .rename = xmp_rename, + .create = xmp_create, + .release = xmp_release, +}; + +int main(int argc, char *argv[]) +{ + umask(0); + return fuse_main(argc, argv, &xmp_oper, NULL); +} -- cgit v1.2.3