diff options
author | Bernd Schubert <bernd.schubert@fastmail.fm> | 2024-03-20 15:25:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-20 15:25:41 +0100 |
commit | 9a823df6d91869960b733581dc71ccefcbe92cc3 (patch) | |
tree | 11c129e0c112934f36d9dca5825e2d0feef11e87 | |
parent | b4804ce3f851945ff4a38e91de918ce4c2ce1a71 (diff) | |
download | libfuse-9a823df6d91869960b733581dc71ccefcbe92cc3.tar.gz |
Fix example/fix-notify_inval_inode.c (#908)
Similar issue as fixed in commit
3c7ba570 "examples/notify_store_retrieve: Add a clean shutdown".
Basically a clean shutdown was missing, but even with clean
shutdown it does not work, as kernel side releases inodes before
sending FUSE_DESTROY - the intervaled thread then gets
-ENOENT.
Co-authored-by: Bernd Schubert <bschubert@ddn.com>
-rw-r--r-- | example/notify_inval_inode.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/example/notify_inval_inode.c b/example/notify_inval_inode.c index b3b50aa..b1fb8f7 100644 --- a/example/notify_inval_inode.c +++ b/example/notify_inval_inode.c @@ -71,6 +71,8 @@ #include <stddef.h> #include <unistd.h> #include <pthread.h> +#include <stdbool.h> +#include <stdatomic.h> /* We can't actually tell the kernel that there is no timeout, so we just send a big value */ @@ -82,6 +84,7 @@ static char file_contents[MAX_STR_LEN]; static int lookup_cnt = 0; static size_t file_size; +static _Atomic bool is_stop = false; /* Command line parsing */ struct options { @@ -120,6 +123,13 @@ static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) { return 0; } +static void tfs_destroy(void *userarg) +{ + (void)userarg; + + is_stop = true; +} + static void tfs_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { struct fuse_entry_param e; @@ -240,6 +250,7 @@ static void tfs_read(fuse_req_t req, fuse_ino_t ino, size_t size, } static const struct fuse_lowlevel_ops tfs_oper = { + .destroy = tfs_destroy, .lookup = tfs_lookup, .getattr = tfs_getattr, .readdir = tfs_readdir, @@ -263,13 +274,24 @@ static void update_fs(void) { static void* update_fs_loop(void *data) { struct fuse_session *se = (struct fuse_session*) data; - while(1) { + while(!is_stop) { update_fs(); if (!options.no_notify && lookup_cnt) { - /* Only send notification if the kernel - is aware of the inode */ - assert(fuse_lowlevel_notify_inval_inode - (se, FILE_INO, 0, 0) == 0); + /* Only send notification if the kernel is aware of the inode */ + + /* Some errors (ENOENT, EBADFD, ENODEV) have to be accepted as the + * might come up during umount, when kernel side already releases + * all inodes, but does not send FUSE_DESTROY yet. + */ + int ret = + fuse_lowlevel_notify_inval_inode(se, FILE_INO, 0, 0); + if ((ret != 0 && !is_stop) && + ret != -ENOENT && ret != -EBADFD && ret != -ENODEV) { + fprintf(stderr, + "ERROR: fuse_lowlevel_notify_store() failed with %s (%d)\n", + strerror(-ret), -ret); + abort(); + } } sleep(options.update_interval); } |