Merge pull request #6 from jmmv/cache-options

Make cache parameters configurable
This commit is contained in:
Nikolaus Rath 2016-02-16 10:47:06 -08:00
commit 451f2075f2
3 changed files with 44 additions and 22 deletions

View File

@ -3,6 +3,10 @@ Draft notes for upcoming release
* Integrated osxfuse's copy of sshfs, which means that sshfs now works
on OS X out of the box.
* Added -o cache_max_size=N option to let users tune the maximum size of
the cache in number of entries.
* Added -o cache_clean_interval=N and -o cache_min_clean_interval=N
options to let users tune the cleaning behavior of the cache.
Release 2.7 (2015-01-28)
------------------------

55
cache.c
View File

@ -14,16 +14,19 @@
#include <glib.h>
#include <pthread.h>
#define DEFAULT_CACHE_TIMEOUT 20
#define MAX_CACHE_SIZE 10000
#define MIN_CACHE_CLEAN_INTERVAL 5
#define CACHE_CLEAN_INTERVAL 60
#define DEFAULT_CACHE_TIMEOUT_SECS 20
#define DEFAULT_MAX_CACHE_SIZE 10000
#define DEFAULT_CACHE_CLEAN_INTERVAL_SECS 60
#define DEFAULT_MIN_CACHE_CLEAN_INTERVAL_SECS 5
struct cache {
int on;
unsigned stat_timeout;
unsigned dir_timeout;
unsigned link_timeout;
unsigned int stat_timeout_secs;
unsigned int dir_timeout_secs;
unsigned int link_timeout_secs;
unsigned int max_size;
unsigned int clean_interval_secs;
unsigned int min_clean_interval_secs;
struct fuse_cache_operations *next_oper;
GHashTable *table;
pthread_mutex_t lock;
@ -70,9 +73,9 @@ static int cache_clean_entry(void *key_, struct node *node, time_t *now)
static void cache_clean(void)
{
time_t now = time(NULL);
if (now > cache.last_cleaned + MIN_CACHE_CLEAN_INTERVAL &&
(g_hash_table_size(cache.table) > MAX_CACHE_SIZE ||
now > cache.last_cleaned + CACHE_CLEAN_INTERVAL)) {
if (now > cache.last_cleaned + cache.min_clean_interval_secs &&
(g_hash_table_size(cache.table) > cache.max_size ||
now > cache.last_cleaned + cache.clean_interval_secs)) {
g_hash_table_foreach_remove(cache.table,
(GHRFunc) cache_clean_entry, &now);
cache.last_cleaned = now;
@ -172,7 +175,7 @@ void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr)
if (wrctr == cache.write_ctr) {
node = cache_get(path);
node->stat = *stbuf;
node->stat_valid = time(NULL) + cache.stat_timeout;
node->stat_valid = time(NULL) + cache.stat_timeout_secs;
if (node->stat_valid > node->valid)
node->valid = node->stat_valid;
cache_clean();
@ -188,7 +191,7 @@ static void cache_add_dir(const char *path, char **dir)
node = cache_get(path);
g_strfreev(node->dir);
node->dir = dir;
node->dir_valid = time(NULL) + cache.dir_timeout;
node->dir_valid = time(NULL) + cache.dir_timeout_secs;
if (node->dir_valid > node->valid)
node->valid = node->dir_valid;
cache_clean();
@ -210,7 +213,7 @@ static void cache_add_link(const char *path, const char *link, size_t size)
node = cache_get(path);
g_free(node->link);
node->link = g_strndup(link, my_strnlen(link, size-1));
node->link_valid = time(NULL) + cache.link_timeout;
node->link_valid = time(NULL) + cache.link_timeout_secs;
if (node->link_valid > node->valid)
node->valid = node->link_valid;
cache_clean();
@ -570,20 +573,28 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *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), 0 },
{ "cache_timeout=%u", offsetof(struct cache, dir_timeout), 0 },
{ "cache_timeout=%u", offsetof(struct cache, link_timeout), 0 },
{ "cache_stat_timeout=%u", offsetof(struct cache, stat_timeout), 0 },
{ "cache_dir_timeout=%u", offsetof(struct cache, dir_timeout), 0 },
{ "cache_link_timeout=%u", offsetof(struct cache, link_timeout), 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 },
{ "cache_stat_timeout=%u", offsetof(struct cache, stat_timeout_secs), 0 },
{ "cache_dir_timeout=%u", offsetof(struct cache, dir_timeout_secs), 0 },
{ "cache_link_timeout=%u", offsetof(struct cache, link_timeout_secs), 0 },
{ "cache_max_size=%u", offsetof(struct cache, max_size), 0 },
{ "cache_clean_interval=%u", offsetof(struct cache,
clean_interval_secs), 0 },
{ "cache_min_clean_interval=%u", offsetof(struct cache,
min_clean_interval_secs), 0 },
FUSE_OPT_END
};
int cache_parse_options(struct fuse_args *args)
{
cache.stat_timeout = DEFAULT_CACHE_TIMEOUT;
cache.dir_timeout = DEFAULT_CACHE_TIMEOUT;
cache.link_timeout = DEFAULT_CACHE_TIMEOUT;
cache.stat_timeout_secs = DEFAULT_CACHE_TIMEOUT_SECS;
cache.dir_timeout_secs = DEFAULT_CACHE_TIMEOUT_SECS;
cache.link_timeout_secs = DEFAULT_CACHE_TIMEOUT_SECS;
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);

View File

@ -3377,8 +3377,15 @@ static void usage(const char *progname)
" -o sync_readdir synchronous readdir\n"
" -o sshfs_debug print some debugging information\n"
" -o cache=BOOL enable caching {yes,no} (default: yes)\n"
" -o cache_max_size=N sets the maximum size of the cache (default: 10000)\n"
" -o cache_timeout=N sets timeout for caches in seconds (default: 20)\n"
" -o cache_X_timeout=N sets timeout for {stat,dir,link} cache\n"
" -o cache_clean_interval=N\n"
" sets the interval for automatic cleaning of the\n"
" cache (default: 60)\n"
" -o cache_min_clean_interval=N\n"
" sets the interval for forced cleaning of the\n"
" cache if full (default: 5)\n"
" -o workaround=LIST colon separated list of workarounds\n"
" none no workarounds enabled\n"
" all all workarounds enabled\n"