From c711bf738f7e78ecb05acc6097088ea07646d3c0 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Wed, 21 Jun 2017 10:59:13 -0700 Subject: Re-enabled cache support. --- cache.c | 263 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 138 insertions(+), 125 deletions(-) (limited to 'cache.c') diff --git a/cache.c b/cache.c index 6a17106..4d9cb0b 100644 --- a/cache.c +++ b/cache.c @@ -8,6 +8,7 @@ #include "cache.h" #include +#include #include #include #include @@ -27,7 +28,7 @@ struct cache { unsigned int max_size; unsigned int clean_interval_secs; unsigned int min_clean_interval_secs; - struct fuse_cache_operations *next_oper; + struct fuse_operations *next_oper; GHashTable *table; pthread_mutex_t lock; time_t last_cleaned; @@ -46,14 +47,22 @@ struct node { time_t valid; }; -struct fuse_cache_dirhandle { +struct readdir_handle { const char *path; - fuse_dirh_t h; - fuse_dirfil_t filler; + void *buf; + fuse_fill_dir_t filler; GPtrArray *dir; uint64_t wrctr; }; +struct file_handle { + /* Did we send an open request to the underlying fs? */ + int is_open; + + /* If so, this will hold its handle */ + unsigned long fs_fh; +}; + static void free_node(gpointer node_) { struct node *node = (struct node *) node_; @@ -108,15 +117,12 @@ static void cache_purge_parent(const char *path) void cache_invalidate(const char *path) { - if (!cache.on) - return; - pthread_mutex_lock(&cache.lock); cache_purge(path); pthread_mutex_unlock(&cache.lock); } -void cache_invalidate_write(const char *path) +static void cache_invalidate_write(const char *path) { pthread_mutex_lock(&cache.lock); cache_purge(path); @@ -168,9 +174,6 @@ void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr) { struct node *node; - if (!cache.on) - return; - pthread_mutex_lock(&cache.lock); if (wrctr == cache.write_ctr) { node = cache_get(path); @@ -253,7 +256,7 @@ static int cache_getattr(const char *path, struct stat *stbuf) int err = cache_get_attr(path, stbuf); if (err) { uint64_t wrctr = cache_get_write_ctr(); - err = cache.next_oper->oper.getattr(path, stbuf); + err = cache.next_oper->getattr(path, stbuf); if (!err) cache_add_attr(path, stbuf, wrctr); } @@ -277,17 +280,52 @@ static int cache_readlink(const char *path, char *buf, size_t size) } } pthread_mutex_unlock(&cache.lock); - err = cache.next_oper->oper.readlink(path, buf, size); + err = cache.next_oper->readlink(path, buf, size); if (!err) cache_add_link(path, buf, size); return err; } -static int cache_dirfill(fuse_cache_dirh_t ch, const char *name, - const struct stat *stbuf) + +static int cache_opendir(const char *path, struct fuse_file_info *fi) +{ + (void) path; + struct file_handle *cfi; + + cfi = malloc(sizeof(struct file_handle)); + if(cfi == NULL) + return -ENOMEM; + cfi->is_open = 0; + fi->fh = (unsigned long) cfi; + return 0; +} + +static int cache_releasedir(const char *path, struct fuse_file_info *fi) +{ + int err; + struct file_handle *cfi; + + cfi = (struct file_handle*) fi->fh; + + if(cfi->is_open) { + fi->fh = cfi->fs_fh; + err = cache.next_oper->releasedir(path, fi); + } else + err = 0; + + free(cfi); + return err; +} + +static int cache_dirfill (void *buf, const char *name, + const struct stat *stbuf, off_t off) { - int err = ch->filler(ch->h, name, 0, 0); + int err; + struct readdir_handle *ch; + + ch = (struct readdir_handle*) buf; + err = ch->filler(ch->buf, name, stbuf, off); if (!err) { g_ptr_array_add(ch->dir, g_strdup(name)); if (stbuf->st_mode & S_IFMT) { @@ -302,61 +340,65 @@ static int cache_dirfill(fuse_cache_dirh_t ch, const char *name, return err; } -static int cache_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) +static int cache_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) { - struct fuse_cache_dirhandle ch; + struct readdir_handle ch; + struct file_handle *cfi; int err; char **dir; struct node *node; + assert(offset == 0); + pthread_mutex_lock(&cache.lock); node = cache_lookup(path); if (node != NULL && node->dir != NULL) { time_t now = time(NULL); if (node->dir_valid - now >= 0) { for(dir = node->dir; *dir != NULL; dir++) - filler(h, *dir, 0, 0); + // FIXME: What about st_mode? + filler(buf, *dir, 0, 0); pthread_mutex_unlock(&cache.lock); return 0; } } pthread_mutex_unlock(&cache.lock); + cfi = (struct file_handle*) fi->fh; + if(cfi->is_open) + fi->fh = cfi->fs_fh; + else { + if(cache.next_oper->opendir) { + err = cache.next_oper->opendir(path, fi); + if(err) + return err; + } + cfi->is_open = 1; + cfi->fs_fh = fi->fh; + } + ch.path = path; - ch.h = h; + ch.buf = buf; ch.filler = filler; ch.dir = g_ptr_array_new(); ch.wrctr = cache_get_write_ctr(); - err = cache.next_oper->cache_getdir(path, &ch, cache_dirfill); + err = cache.next_oper->readdir(path, &ch, cache_dirfill, offset, fi); g_ptr_array_add(ch.dir, NULL); dir = (char **) ch.dir->pdata; - if (!err) + if (!err) { cache_add_dir(path, dir); - else + } else { g_strfreev(dir); + } g_ptr_array_free(ch.dir, FALSE); - return err; -} -static int cache_unity_dirfill(fuse_cache_dirh_t ch, const char *name, - const struct stat *stbuf) -{ - (void) stbuf; - return ch->filler(ch->h, name, 0, 0); -} - -static int cache_unity_getdir(const char *path, fuse_dirh_t h, - fuse_dirfil_t filler) -{ - struct fuse_cache_dirhandle ch; - ch.h = h; - ch.filler = filler; - return cache.next_oper->cache_getdir(path, &ch, cache_unity_dirfill); + return err; } static int cache_mknod(const char *path, mode_t mode, dev_t rdev) { - int err = cache.next_oper->oper.mknod(path, mode, rdev); + int err = cache.next_oper->mknod(path, mode, rdev); if (!err) cache_invalidate_dir(path); return err; @@ -364,7 +406,7 @@ static int cache_mknod(const char *path, mode_t mode, dev_t rdev) static int cache_mkdir(const char *path, mode_t mode) { - int err = cache.next_oper->oper.mkdir(path, mode); + int err = cache.next_oper->mkdir(path, mode); if (!err) cache_invalidate_dir(path); return err; @@ -372,7 +414,7 @@ static int cache_mkdir(const char *path, mode_t mode) static int cache_unlink(const char *path) { - int err = cache.next_oper->oper.unlink(path); + int err = cache.next_oper->unlink(path); if (!err) cache_invalidate_dir(path); return err; @@ -380,7 +422,7 @@ static int cache_unlink(const char *path) static int cache_rmdir(const char *path) { - int err = cache.next_oper->oper.rmdir(path); + int err = cache.next_oper->rmdir(path); if (!err) cache_invalidate_dir(path); return err; @@ -388,7 +430,7 @@ static int cache_rmdir(const char *path) static int cache_symlink(const char *from, const char *to) { - int err = cache.next_oper->oper.symlink(from, to); + int err = cache.next_oper->symlink(from, to); if (!err) cache_invalidate_dir(to); return err; @@ -396,7 +438,7 @@ static int cache_symlink(const char *from, const char *to) static int cache_rename(const char *from, const char *to) { - int err = cache.next_oper->oper.rename(from, to); + int err = cache.next_oper->rename(from, to); if (!err) cache_do_rename(from, to); return err; @@ -404,7 +446,7 @@ static int cache_rename(const char *from, const char *to) static int cache_link(const char *from, const char *to) { - int err = cache.next_oper->oper.link(from, to); + int err = cache.next_oper->link(from, to); if (!err) { cache_invalidate(from); cache_invalidate_dir(to); @@ -414,7 +456,7 @@ static int cache_link(const char *from, const char *to) static int cache_chmod(const char *path, mode_t mode) { - int err = cache.next_oper->oper.chmod(path, mode); + int err = cache.next_oper->chmod(path, mode); if (!err) cache_invalidate(path); return err; @@ -422,7 +464,7 @@ static int cache_chmod(const char *path, mode_t mode) static int cache_chown(const char *path, uid_t uid, gid_t gid) { - int err = cache.next_oper->oper.chown(path, uid, gid); + int err = cache.next_oper->chown(path, uid, gid); if (!err) cache_invalidate(path); return err; @@ -430,7 +472,7 @@ static int cache_chown(const char *path, uid_t uid, gid_t gid) static int cache_truncate(const char *path, off_t size) { - int err = cache.next_oper->oper.truncate(path, size); + int err = cache.next_oper->truncate(path, size); if (!err) cache_invalidate(path); return err; @@ -438,7 +480,7 @@ static int cache_truncate(const char *path, off_t size) static int cache_utime(const char *path, struct utimbuf *buf) { - int err = cache.next_oper->oper.utime(path, buf); + int err = cache.next_oper->utime(path, buf); if (!err) cache_invalidate(path); return err; @@ -447,7 +489,7 @@ static int cache_utime(const char *path, struct utimbuf *buf) static int cache_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - int res = cache.next_oper->oper.write(path, buf, size, offset, fi); + int res = cache.next_oper->write(path, buf, size, offset, fi); if (res >= 0) cache_invalidate_write(path); return res; @@ -456,7 +498,7 @@ static int cache_write(const char *path, const char *buf, size_t size, static int cache_create(const char *path, mode_t mode, struct fuse_file_info *fi) { - int err = cache.next_oper->oper.create(path, mode, fi); + int err = cache.next_oper->create(path, mode, fi); if (!err) cache_invalidate_dir(path); return err; @@ -465,7 +507,7 @@ static int cache_create(const char *path, mode_t mode, static int cache_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) { - int err = cache.next_oper->oper.ftruncate(path, size, fi); + int err = cache.next_oper->ftruncate(path, size, fi); if (!err) cache_invalidate(path); return err; @@ -477,97 +519,69 @@ static int cache_fgetattr(const char *path, struct stat *stbuf, int err = cache_get_attr(path, stbuf); if (err) { uint64_t wrctr = cache_get_write_ctr(); - err = cache.next_oper->oper.fgetattr(path, stbuf, fi); + err = cache.next_oper->fgetattr(path, stbuf, fi); if (!err) cache_add_attr(path, stbuf, wrctr); } return err; } -static void cache_unity_fill(struct fuse_cache_operations *oper, - struct fuse_operations *cache_oper) -{ - cache_oper->init = oper->oper.init; - cache_oper->getattr = oper->oper.getattr; - cache_oper->access = oper->oper.access; - cache_oper->readlink = oper->oper.readlink; - cache_oper->getdir = cache_unity_getdir; - cache_oper->mknod = oper->oper.mknod; - cache_oper->mkdir = oper->oper.mkdir; - cache_oper->symlink = oper->oper.symlink; - cache_oper->unlink = oper->oper.unlink; - cache_oper->rmdir = oper->oper.rmdir; - cache_oper->rename = oper->oper.rename; - cache_oper->link = oper->oper.link; - cache_oper->chmod = oper->oper.chmod; - cache_oper->chown = oper->oper.chown; - cache_oper->truncate = oper->oper.truncate; - cache_oper->utime = oper->oper.utime; - cache_oper->open = oper->oper.open; - cache_oper->read = oper->oper.read; - cache_oper->write = oper->oper.write; - cache_oper->flush = oper->oper.flush; - cache_oper->release = oper->oper.release; - cache_oper->fsync = oper->oper.fsync; - cache_oper->statfs = oper->oper.statfs; - cache_oper->setxattr = oper->oper.setxattr; - cache_oper->getxattr = oper->oper.getxattr; - cache_oper->listxattr = oper->oper.listxattr; - cache_oper->removexattr = oper->oper.removexattr; - cache_oper->create = oper->oper.create; - cache_oper->ftruncate = oper->oper.ftruncate; - cache_oper->fgetattr = oper->oper.fgetattr; - cache_oper->flag_nullpath_ok = oper->oper.flag_nullpath_ok; - cache_oper->flag_nopath = oper->oper.flag_nopath; -} - -static void cache_fill(struct fuse_cache_operations *oper, +static void cache_fill(struct fuse_operations *oper, struct fuse_operations *cache_oper) { - cache_oper->getattr = oper->oper.getattr ? cache_getattr : NULL; - cache_oper->readlink = oper->oper.readlink ? cache_readlink : NULL; - cache_oper->getdir = oper->cache_getdir ? cache_getdir : NULL; - cache_oper->mknod = oper->oper.mknod ? cache_mknod : NULL; - cache_oper->mkdir = oper->oper.mkdir ? cache_mkdir : NULL; - cache_oper->symlink = oper->oper.symlink ? cache_symlink : NULL; - cache_oper->unlink = oper->oper.unlink ? cache_unlink : NULL; - cache_oper->rmdir = oper->oper.rmdir ? cache_rmdir : NULL; - cache_oper->rename = oper->oper.rename ? cache_rename : NULL; - cache_oper->link = oper->oper.link ? cache_link : NULL; - cache_oper->chmod = oper->oper.chmod ? cache_chmod : NULL; - cache_oper->chown = oper->oper.chown ? cache_chown : NULL; - cache_oper->truncate = oper->oper.truncate ? cache_truncate : NULL; - cache_oper->utime = oper->oper.utime ? cache_utime : NULL; - cache_oper->write = oper->oper.write ? cache_write : NULL; - cache_oper->create = oper->oper.create ? cache_create : NULL; - cache_oper->ftruncate = oper->oper.ftruncate ? cache_ftruncate : NULL; - cache_oper->fgetattr = oper->oper.fgetattr ? cache_fgetattr : NULL; + cache_oper->access = oper->access; + cache_oper->chmod = oper->chmod ? cache_chmod : NULL; + cache_oper->chown = oper->chown ? cache_chown : NULL; + cache_oper->create = oper->create ? cache_create : NULL; + cache_oper->fgetattr = oper->fgetattr ? cache_fgetattr : NULL; + cache_oper->flush = oper->flush; + cache_oper->fsync = oper->fsync; + cache_oper->ftruncate = oper->ftruncate ? cache_ftruncate : NULL; + cache_oper->getattr = oper->getattr ? cache_getattr : NULL; + cache_oper->getxattr = oper->getxattr; + cache_oper->init = oper->init; + cache_oper->link = oper->link ? cache_link : NULL; + cache_oper->listxattr = oper->listxattr; + cache_oper->mkdir = oper->mkdir ? cache_mkdir : NULL; + cache_oper->mknod = oper->mknod ? cache_mknod : NULL; + cache_oper->open = oper->open; + cache_oper->opendir = cache_opendir; + cache_oper->read = oper->read; + cache_oper->readdir = oper->readdir ? cache_readdir : NULL; + cache_oper->readlink = oper->readlink ? cache_readlink : NULL; + cache_oper->release = oper->release; + cache_oper->releasedir = cache_releasedir; + cache_oper->removexattr = oper->removexattr; + cache_oper->rename = oper->rename ? cache_rename : NULL; + cache_oper->rmdir = oper->rmdir ? cache_rmdir : NULL; + cache_oper->setxattr = oper->setxattr; + cache_oper->statfs = oper->statfs; + cache_oper->symlink = oper->symlink ? cache_symlink : NULL; + cache_oper->truncate = oper->truncate ? cache_truncate : NULL; + cache_oper->unlink = oper->unlink ? cache_unlink : NULL; + cache_oper->utime = oper->utime ? cache_utime : NULL; + cache_oper->write = oper->write ? cache_write : NULL; + cache_oper->flag_nopath = 0; cache_oper->flag_nullpath_ok = 0; - cache_oper->flag_nopath = 0; } -struct fuse_operations *cache_init(struct fuse_cache_operations *oper) +struct fuse_operations *cache_init(struct fuse_operations *oper) { static struct fuse_operations cache_oper; cache.next_oper = oper; - cache_unity_fill(oper, &cache_oper); - if (cache.on) { - cache_fill(oper, &cache_oper); - pthread_mutex_init(&cache.lock, NULL); - cache.table = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, free_node); - if (cache.table == NULL) { - fprintf(stderr, "failed to create cache\n"); - return NULL; - } + cache_fill(oper, &cache_oper); + pthread_mutex_init(&cache.lock, NULL); + cache.table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, free_node); + if (cache.table == NULL) { + fprintf(stderr, "failed to create cache\n"); + return NULL; } return &cache_oper; } static const struct fuse_opt cache_opts[] = { - { "cache=yes", offsetof(struct cache, on), 1 }, - { "cache=no", offsetof(struct cache, on), 0 }, { "cache_timeout=%u", offsetof(struct cache, stat_timeout_secs), 0 }, { "cache_timeout=%u", offsetof(struct cache, dir_timeout_secs), 0 }, { "cache_timeout=%u", offsetof(struct cache, link_timeout_secs), 0 }, @@ -590,7 +604,6 @@ int cache_parse_options(struct fuse_args *args) cache.max_size = DEFAULT_MAX_CACHE_SIZE; cache.clean_interval_secs = DEFAULT_CACHE_CLEAN_INTERVAL_SECS; cache.min_clean_interval_secs = DEFAULT_MIN_CACHE_CLEAN_INTERVAL_SECS; - cache.on = 1; return fuse_opt_parse(args, &cache, cache_opts, NULL); } -- cgit v1.2.3