Re-enabled cache support.
This commit is contained in:
parent
493081e8f6
commit
c711bf738f
263
cache.c
263
cache.c
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "cache.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -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)
|
||||
{
|
||||
int err = ch->filler(ch->h, name, 0, 0);
|
||||
(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;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
11
cache.h
11
cache.h
|
|
@ -9,16 +9,7 @@
|
|||
#include <fuse.h>
|
||||
#include <fuse_opt.h>
|
||||
|
||||
typedef struct fuse_cache_dirhandle *fuse_cache_dirh_t;
|
||||
typedef int (*fuse_cache_dirfil_t) (fuse_cache_dirh_t h, const char *name,
|
||||
const struct stat *stbuf);
|
||||
|
||||
struct fuse_cache_operations {
|
||||
struct fuse_operations oper;
|
||||
int (*cache_getdir) (const char *, fuse_cache_dirh_t, fuse_cache_dirfil_t);
|
||||
};
|
||||
|
||||
struct fuse_operations *cache_init(struct fuse_cache_operations *oper);
|
||||
struct fuse_operations *cache_init(struct fuse_operations *oper);
|
||||
int cache_parse_options(struct fuse_args *args);
|
||||
void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr);
|
||||
void cache_invalidate(const char *path);
|
||||
|
|
|
|||
32
sshfs.c
32
sshfs.c
|
|
@ -224,6 +224,7 @@ struct sshfs {
|
|||
int idmap;
|
||||
int nomap;
|
||||
int disable_hardlink;
|
||||
int cache;
|
||||
char *uid_file;
|
||||
char *gid_file;
|
||||
GHashTable *uid_map;
|
||||
|
|
@ -403,6 +404,8 @@ static struct fuse_opt sshfs_opts[] = {
|
|||
SSHFS_OPT("delay_connect", delay_connect, 1),
|
||||
SSHFS_OPT("slave", slave, 1),
|
||||
SSHFS_OPT("disable_hardlink", disable_hardlink, 1),
|
||||
SSHFS_OPT("cache=yes", cache, 1),
|
||||
SSHFS_OPT("cache=no", cache, 0),
|
||||
|
||||
FUSE_OPT_KEY("-p ", KEY_PORT),
|
||||
FUSE_OPT_KEY("-C", KEY_COMPRESS),
|
||||
|
|
@ -2447,7 +2450,10 @@ static int sshfs_open_common(const char *path, mode_t mode,
|
|||
uint32_t pflags = 0;
|
||||
struct iovec iov;
|
||||
uint8_t type;
|
||||
uint64_t wrctr = cache_get_write_ctr();
|
||||
uint64_t wrctr = 0;
|
||||
|
||||
if (sshfs.cache)
|
||||
wrctr = cache_get_write_ctr();
|
||||
|
||||
if ((fi->flags & O_ACCMODE) == O_RDONLY)
|
||||
pflags = SSH_FXF_READ;
|
||||
|
|
@ -2504,11 +2510,13 @@ static int sshfs_open_common(const char *path, mode_t mode,
|
|||
}
|
||||
|
||||
if (!err) {
|
||||
cache_add_attr(path, &stbuf, wrctr);
|
||||
if (sshfs.cache)
|
||||
cache_add_attr(path, &stbuf, wrctr);
|
||||
buf_finish(&sf->handle);
|
||||
fi->fh = (unsigned long) sf;
|
||||
} else {
|
||||
cache_invalidate(path);
|
||||
if (sshfs.cache)
|
||||
cache_invalidate(path);
|
||||
g_free(sf);
|
||||
}
|
||||
buf_free(&buf);
|
||||
|
|
@ -3234,8 +3242,7 @@ static int processing_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct fuse_cache_operations sshfs_oper = {
|
||||
.oper = {
|
||||
static struct fuse_operations sshfs_oper = {
|
||||
.init = sshfs_init,
|
||||
.getattr = sshfs_getattr,
|
||||
.access = sshfs_access,
|
||||
|
|
@ -3266,8 +3273,6 @@ static struct fuse_cache_operations sshfs_oper = {
|
|||
.fgetattr = sshfs_fgetattr,
|
||||
.flag_nullpath_ok = 1,
|
||||
.flag_nopath = 1,
|
||||
},
|
||||
// .cache_readdir = sshfs_readdir,
|
||||
};
|
||||
|
||||
static void usage(const char *progname)
|
||||
|
|
@ -3812,6 +3817,7 @@ int main(int argc, char *argv[])
|
|||
sshfs.rfd = -1;
|
||||
sshfs.wfd = -1;
|
||||
sshfs.ptyfd = -1;
|
||||
sshfs.cache = 1;
|
||||
sshfs.ptyslavefd = -1;
|
||||
sshfs.delay_connect = 0;
|
||||
sshfs.slave = 0;
|
||||
|
|
@ -3837,8 +3843,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
// These workarounds require the "path" argument.
|
||||
if (sshfs.truncate_workaround || sshfs.fstat_workaround) {
|
||||
sshfs_oper.oper.flag_nullpath_ok = 0;
|
||||
sshfs_oper.oper.flag_nopath = 0;
|
||||
sshfs_oper.flag_nullpath_ok = 0;
|
||||
sshfs_oper.flag_nopath = 0;
|
||||
}
|
||||
|
||||
if (sshfs.idmap == IDMAP_USER)
|
||||
|
|
@ -3977,9 +3983,11 @@ int main(int argc, char *argv[])
|
|||
perror("WARNING: failed to set FD_CLOEXEC on fuse device");
|
||||
#endif
|
||||
|
||||
sshfs.op = cache_init(&sshfs_oper);
|
||||
// FIXME: Bypass cache for now
|
||||
fuse = fuse_new(ch, &args, &sshfs_oper.oper,
|
||||
if(sshfs.cache)
|
||||
sshfs.op = cache_init(&sshfs_oper);
|
||||
else
|
||||
sshfs.op = &sshfs_oper;
|
||||
fuse = fuse_new(ch, &args, sshfs.op,
|
||||
sizeof(struct fuse_operations), NULL);
|
||||
if (fuse == NULL) {
|
||||
fuse_unmount(mountpoint, ch);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
|
|||
if cache_timeout == 0:
|
||||
cmdline += [ '-o', 'cache=no' ]
|
||||
else:
|
||||
cmdline += [ '-o', 'cache_timeout=%d' % cache_timeout ]
|
||||
cmdline += [ '-o', 'cache_timeout=%d' % cache_timeout,
|
||||
'-o', 'cache=yes' ]
|
||||
|
||||
# FUSE Cache
|
||||
cmdline += [ '-o', 'entry_timeout=0',
|
||||
|
|
|
|||
Loading…
Reference in New Issue