From fc83143867a37e34a51ce5a6d763b46715abf02d Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Thu, 24 Aug 2017 14:23:13 +0200 Subject: Renamed notify_inval_inode_fh to invalidate_path The previous name didn't make much sense. --- example/Makefile.am | 2 +- example/invalidate_path.c | 292 ++++++++++++++++++++++++++++++++++++++++ example/meson.build | 2 +- example/notify_inval_inode_fh.c | 292 ---------------------------------------- test/test_ctests.py | 4 +- 5 files changed, 296 insertions(+), 296 deletions(-) create mode 100644 example/invalidate_path.c delete mode 100644 example/notify_inval_inode_fh.c diff --git a/example/Makefile.am b/example/Makefile.am index e9a315e..9a3940e 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -D_REENTRANT noinst_HEADERS = ioctl.h noinst_PROGRAMS = passthrough passthrough_fh null hello hello_ll \ ioctl ioctl_client poll poll_client passthrough_ll \ - notify_inval_inode notify_inval_inode_fh \ + notify_inval_inode invalidate_path \ notify_store_retrieve notify_inval_entry \ cuse cuse_client printcap diff --git a/example/invalidate_path.c b/example/invalidate_path.c new file mode 100644 index 0000000..afa1339 --- /dev/null +++ b/example/invalidate_path.c @@ -0,0 +1,292 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2016 Nikolaus Rath + (C) 2017 EditShare LLC + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + */ + +/** @file + * + * This example implements a file system with two files: + * * 'current-time', whose contents change dynamically: + * it always contains the current time (same as in + * notify_inval_inode.c). + * * 'growing', whose size changes dynamically, growing + * by 1 byte after each update. This aims to check + * if cached file metadata is also invalidated. + * + * ## Compilation ## + * + * gcc -Wall @file `pkg-config fuse3 --cflags --libs` -o invalidate_path + * + * ## Source code ## + * \include @file + */ + +#define FUSE_USE_VERSION 31 + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include /* for fuse_cmdline_opts */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* We can't actually tell the kernel that there is no + timeout, so we just send a big value */ +#define NO_TIMEOUT 500000 + +#define MAX_STR_LEN 128 +#define TIME_FILE_NAME "current_time" +#define TIME_FILE_INO 2 +#define GROW_FILE_NAME "growing" +#define GROW_FILE_INO 3 + +static char time_file_contents[MAX_STR_LEN]; +static size_t grow_file_size; + +/* Command line parsing */ +struct options { + int no_notify; + int update_interval; +}; +static struct options options = { + .no_notify = 0, + .update_interval = 1, +}; + +#define OPTION(t, p) { t, offsetof(struct options, p), 1 } +static const struct fuse_opt option_spec[] = { + OPTION("--no-notify", no_notify), + OPTION("--update-interval=%d", update_interval), + FUSE_OPT_END +}; + +static void *xmp_init(struct fuse_conn_info *conn, struct fuse_config *cfg) +{ + (void) conn; + cfg->entry_timeout = NO_TIMEOUT; + cfg->attr_timeout = NO_TIMEOUT; + cfg->negative_timeout = 0; + + return NULL; +} + +static int xmp_getattr(const char *path, + struct stat *stbuf, struct fuse_file_info* fi) { + (void) fi; + if (strcmp(path, "/") == 0) { + stbuf->st_ino = 1; + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 1; + } else if (strcmp(path, "/" TIME_FILE_NAME) == 0) { + stbuf->st_ino = TIME_FILE_INO; + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_size = strlen(time_file_contents); + } else if (strcmp(path, "/" GROW_FILE_NAME) == 0) { + stbuf->st_ino = GROW_FILE_INO; + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_size = grow_file_size; + } else { + return -ENOENT; + } + + return 0; +} + +static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi, + enum fuse_readdir_flags flags) { + (void) fi; + (void) offset; + (void) flags; + if (strcmp(path, "/") != 0) { + return -ENOTDIR; + } else { + (void) filler; + (void) buf; + struct stat file_stat; + xmp_getattr("/" TIME_FILE_NAME, &file_stat, NULL); + filler(buf, TIME_FILE_NAME, &file_stat, 0, 0); + xmp_getattr("/" GROW_FILE_NAME, &file_stat, NULL); + filler(buf, GROW_FILE_NAME, &file_stat, 0, 0); + return 0; + } +} + +static int xmp_open(const char *path, struct fuse_file_info *fi) { + (void) path; + /* Make cache persistent even if file is closed, + this makes it easier to see the effects */ + fi->keep_cache = 1; + return 0; +} + +static int xmp_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) { + (void) fi; + (void) offset; + if (strcmp(path, "/" TIME_FILE_NAME) == 0) { + int file_length = strlen(time_file_contents); + int to_copy = offset + size <= file_length + ? size + : file_length - offset; + memcpy(buf, time_file_contents, to_copy); + return to_copy; + } else { + assert(strcmp(path, "/" GROW_FILE_NAME) == 0); + int to_copy = offset + size <= grow_file_size + ? size + : grow_file_size - offset; + memset(buf, 'x', to_copy); + return to_copy; + } +} + +static struct fuse_operations xmp_oper = { + .init = xmp_init, + .getattr = xmp_getattr, + .readdir = xmp_readdir, + .open = xmp_open, + .read = xmp_read, +}; + +static void update_fs(void) { + static int count = 0; + struct tm *now; + time_t t; + t = time(NULL); + now = localtime(&t); + assert(now != NULL); + + int time_file_size = strftime(time_file_contents, MAX_STR_LEN, + "The current time is %H:%M:%S\n", now); + assert(time_file_size != 0); + + grow_file_size = count++; +} + +static int invalidate(struct fuse *fuse, const char *path) { + int status = fuse_invalidate_path(fuse, path); + if (status == -ENOENT) { + return 0; + } else { + return status; + } +} + +static void* update_fs_loop(void *data) { + struct fuse *fuse = (struct fuse*) data; + + while (1) { + update_fs(); + if (!options.no_notify) { + assert(invalidate(fuse, "/" TIME_FILE_NAME) == 0); + assert(invalidate(fuse, "/" GROW_FILE_NAME) == 0); + } + sleep(options.update_interval); + } + return NULL; +} + +static void show_help(const char *progname) +{ + printf("usage: %s [options] \n\n", progname); + printf("File-system specific options:\n" + " --update-interval= Update-rate of file system contents\n" + " --no-notify Disable kernel notifications\n" + "\n"); +} + +int main(int argc, char *argv[]) { + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse *fuse; + struct fuse_cmdline_opts opts; + int res; + + /* Initialize the files */ + update_fs(); + + if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1) + return 1; + + if (fuse_parse_cmdline(&args, &opts) != 0) + return 1; + + if (opts.show_version) { + printf("FUSE library version %s\n", fuse_pkgversion()); + fuse_lowlevel_version(); + res = 0; + goto out1; + } else if (opts.show_help) { + show_help(argv[0]); + fuse_cmdline_help(); + fuse_lib_help(&args); + res = 0; + goto out1; + } else if (!opts.mountpoint) { + fprintf(stderr, "error: no mountpoint specified\n"); + res = 1; + goto out1; + } + + fuse = fuse_new(&args, &xmp_oper, sizeof(xmp_oper), NULL); + if (fuse == NULL) { + res = 1; + goto out1; + } + + if (fuse_mount(fuse,opts.mountpoint) != 0) { + res = 1; + goto out2; + } + + if (fuse_daemonize(opts.foreground) != 0) { + res = 1; + goto out3; + } + + pthread_t updater; /* Start thread to update file contents */ + int ret = pthread_create(&updater, NULL, update_fs_loop, (void *) fuse); + if (ret != 0) { + fprintf(stderr, "pthread_create failed with %s\n", strerror(ret)); + return 1; + }; + + struct fuse_session *se = fuse_get_session(fuse); + if (fuse_set_signal_handlers(se) != 0) { + res = 1; + goto out3; + } + + if (opts.singlethread) + res = fuse_loop(fuse); + else + res = fuse_loop_mt(fuse, opts.clone_fd); + if (res) + res = 1; + + fuse_remove_signal_handlers(se); +out3: + fuse_unmount(fuse); +out2: + fuse_destroy(fuse); +out1: + free(opts.mountpoint); + fuse_opt_free_args(&args); + return res; +} diff --git a/example/meson.build b/example/meson.build index 406c4c4..de2de42 100644 --- a/example/meson.build +++ b/example/meson.build @@ -11,7 +11,7 @@ if not platform.endswith('bsd') endif threaded_examples = [ 'notify_inval_inode', - 'notify_inval_inode_fh', + 'invalidate_path', 'notify_store_retrieve', 'notify_inval_entry', 'poll' ] diff --git a/example/notify_inval_inode_fh.c b/example/notify_inval_inode_fh.c deleted file mode 100644 index f37fcef..0000000 --- a/example/notify_inval_inode_fh.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - FUSE: Filesystem in Userspace - Copyright (C) 2016 Nikolaus Rath - (C) 2017 EditShare LLC - - This program can be distributed under the terms of the GNU GPL. - See the file COPYING. - */ - -/** @file - * - * This example implements a file system with two files: - * * 'current-time', whose contents change dynamically: - * it always contains the current time (same as in - * notify_inval_inode.c). - * * 'growing', whose size changes dynamically, growing - * by 1 byte after each update. This aims to check - * if cached file metadata is also invalidated. - * - * ## Compilation ## - * - * gcc -Wall notify_inval_inode_fh.c `pkg-config fuse3 --cflags --libs` -o notify_inval_inode_fh - * - * ## Source code ## - * \include notify_inval_inode_fh.c - */ - -#define FUSE_USE_VERSION 31 - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include /* for fuse_cmdline_opts */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* We can't actually tell the kernel that there is no - timeout, so we just send a big value */ -#define NO_TIMEOUT 500000 - -#define MAX_STR_LEN 128 -#define TIME_FILE_NAME "current_time" -#define TIME_FILE_INO 2 -#define GROW_FILE_NAME "growing" -#define GROW_FILE_INO 3 - -static char time_file_contents[MAX_STR_LEN]; -static size_t grow_file_size; - -/* Command line parsing */ -struct options { - int no_notify; - int update_interval; -}; -static struct options options = { - .no_notify = 0, - .update_interval = 1, -}; - -#define OPTION(t, p) { t, offsetof(struct options, p), 1 } -static const struct fuse_opt option_spec[] = { - OPTION("--no-notify", no_notify), - OPTION("--update-interval=%d", update_interval), - FUSE_OPT_END -}; - -static void *xmp_init(struct fuse_conn_info *conn, struct fuse_config *cfg) -{ - (void) conn; - cfg->entry_timeout = NO_TIMEOUT; - cfg->attr_timeout = NO_TIMEOUT; - cfg->negative_timeout = 0; - - return NULL; -} - -static int xmp_getattr(const char *path, - struct stat *stbuf, struct fuse_file_info* fi) { - (void) fi; - if (strcmp(path, "/") == 0) { - stbuf->st_ino = 1; - stbuf->st_mode = S_IFDIR | 0755; - stbuf->st_nlink = 1; - } else if (strcmp(path, "/" TIME_FILE_NAME) == 0) { - stbuf->st_ino = TIME_FILE_INO; - stbuf->st_mode = S_IFREG | 0444; - stbuf->st_nlink = 1; - stbuf->st_size = strlen(time_file_contents); - } else if (strcmp(path, "/" GROW_FILE_NAME) == 0) { - stbuf->st_ino = GROW_FILE_INO; - stbuf->st_mode = S_IFREG | 0444; - stbuf->st_nlink = 1; - stbuf->st_size = grow_file_size; - } else { - return -ENOENT; - } - - return 0; -} - -static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, - off_t offset, struct fuse_file_info *fi, - enum fuse_readdir_flags flags) { - (void) fi; - (void) offset; - (void) flags; - if (strcmp(path, "/") != 0) { - return -ENOTDIR; - } else { - (void) filler; - (void) buf; - struct stat file_stat; - xmp_getattr("/" TIME_FILE_NAME, &file_stat, NULL); - filler(buf, TIME_FILE_NAME, &file_stat, 0, 0); - xmp_getattr("/" GROW_FILE_NAME, &file_stat, NULL); - filler(buf, GROW_FILE_NAME, &file_stat, 0, 0); - return 0; - } -} - -static int xmp_open(const char *path, struct fuse_file_info *fi) { - (void) path; - /* Make cache persistent even if file is closed, - this makes it easier to see the effects */ - fi->keep_cache = 1; - return 0; -} - -static int xmp_read(const char *path, char *buf, size_t size, off_t offset, - struct fuse_file_info *fi) { - (void) fi; - (void) offset; - if (strcmp(path, "/" TIME_FILE_NAME) == 0) { - int file_length = strlen(time_file_contents); - int to_copy = offset + size <= file_length - ? size - : file_length - offset; - memcpy(buf, time_file_contents, to_copy); - return to_copy; - } else { - assert(strcmp(path, "/" GROW_FILE_NAME) == 0); - int to_copy = offset + size <= grow_file_size - ? size - : grow_file_size - offset; - memset(buf, 'x', to_copy); - return to_copy; - } -} - -static struct fuse_operations xmp_oper = { - .init = xmp_init, - .getattr = xmp_getattr, - .readdir = xmp_readdir, - .open = xmp_open, - .read = xmp_read, -}; - -static void update_fs(void) { - static int count = 0; - struct tm *now; - time_t t; - t = time(NULL); - now = localtime(&t); - assert(now != NULL); - - int time_file_size = strftime(time_file_contents, MAX_STR_LEN, - "The current time is %H:%M:%S\n", now); - assert(time_file_size != 0); - - grow_file_size = count++; -} - -static int invalidate(struct fuse *fuse, const char *path) { - int status = fuse_invalidate_path(fuse, path); - if (status == -ENOENT) { - return 0; - } else { - return status; - } -} - -static void* update_fs_loop(void *data) { - struct fuse *fuse = (struct fuse*) data; - - while (1) { - update_fs(); - if (!options.no_notify) { - assert(invalidate(fuse, "/" TIME_FILE_NAME) == 0); - assert(invalidate(fuse, "/" GROW_FILE_NAME) == 0); - } - sleep(options.update_interval); - } - return NULL; -} - -static void show_help(const char *progname) -{ - printf("usage: %s [options] \n\n", progname); - printf("File-system specific options:\n" - " --update-interval= Update-rate of file system contents\n" - " --no-notify Disable kernel notifications\n" - "\n"); -} - -int main(int argc, char *argv[]) { - struct fuse_args args = FUSE_ARGS_INIT(argc, argv); - struct fuse *fuse; - struct fuse_cmdline_opts opts; - int res; - - /* Initialize the files */ - update_fs(); - - if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1) - return 1; - - if (fuse_parse_cmdline(&args, &opts) != 0) - return 1; - - if (opts.show_version) { - printf("FUSE library version %s\n", fuse_pkgversion()); - fuse_lowlevel_version(); - res = 0; - goto out1; - } else if (opts.show_help) { - show_help(argv[0]); - fuse_cmdline_help(); - fuse_lib_help(&args); - res = 0; - goto out1; - } else if (!opts.mountpoint) { - fprintf(stderr, "error: no mountpoint specified\n"); - res = 1; - goto out1; - } - - fuse = fuse_new(&args, &xmp_oper, sizeof(xmp_oper), NULL); - if (fuse == NULL) { - res = 1; - goto out1; - } - - if (fuse_mount(fuse,opts.mountpoint) != 0) { - res = 1; - goto out2; - } - - if (fuse_daemonize(opts.foreground) != 0) { - res = 1; - goto out3; - } - - pthread_t updater; /* Start thread to update file contents */ - int ret = pthread_create(&updater, NULL, update_fs_loop, (void *) fuse); - if (ret != 0) { - fprintf(stderr, "pthread_create failed with %s\n", strerror(ret)); - return 1; - }; - - struct fuse_session *se = fuse_get_session(fuse); - if (fuse_set_signal_handlers(se) != 0) { - res = 1; - goto out3; - } - - if (opts.singlethread) - res = fuse_loop(fuse); - else - res = fuse_loop_mt(fuse, opts.clone_fd); - if (res) - res = 1; - - fuse_remove_signal_handlers(se); -out3: - fuse_unmount(fuse); -out2: - fuse_destroy(fuse); -out1: - free(opts.mountpoint); - fuse_opt_free_args(&args); - return res; -} diff --git a/test/test_ctests.py b/test/test_ctests.py index 2da55e5..469c867 100644 --- a/test/test_ctests.py +++ b/test/test_ctests.py @@ -35,7 +35,7 @@ def test_write_cache(tmpdir, writeback): subprocess.check_call(cmdline) -names = [ 'notify_inval_inode', 'notify_inval_inode_fh' ] +names = [ 'notify_inval_inode', 'invalidate_path' ] if sys.platform == 'linux': names.append('notify_store_retrieve') @pytest.mark.parametrize("name", names) @@ -70,7 +70,7 @@ def test_notify1(tmpdir, name, notify): def test_notify_file_size(tmpdir, notify): mnt_dir = str(tmpdir) cmdline = base_cmdline + \ - [ pjoin(basename, 'example', 'notify_inval_inode_fh'), + [ pjoin(basename, 'example', 'invalidate_path'), '-f', '--update-interval=1', mnt_dir ] if not notify: cmdline.append('--no-notify') -- cgit v1.2.3