aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-02-09 15:12:51 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-02-09 15:12:51 +0000
commit838fed1a3a2fbe5958fd5051a971496efd3557f3 (patch)
tree67042691893ff6aaced0f71248268f2076a51f6b
parent99acbfff7aab23b386507419759834cb2db2bd30 (diff)
downloadsshfs-838fed1a3a2fbe5958fd5051a971496efd3557f3.tar
sshfs-838fed1a3a2fbe5958fd5051a971496efd3557f3.tar.gz
sshfs-838fed1a3a2fbe5958fd5051a971496efd3557f3.tar.bz2
sshfs-838fed1a3a2fbe5958fd5051a971496efd3557f3.zip
fix
-rw-r--r--cache.c184
-rw-r--r--cache.h1
-rw-r--r--sshfs.c27
3 files changed, 169 insertions, 43 deletions
diff --git a/cache.c b/cache.c
index 040e6df..034121d 100644
--- a/cache.c
+++ b/cache.c
@@ -8,16 +8,24 @@
#include "cache.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <pthread.h>
-#define CACHE_TIMEOUT 20
+#include "opts.h"
+
+#define DEFAULT_CACHE_TIMEOUT 20
#define MAX_CACHE_SIZE 10000
#define MIN_CACHE_CLEAN_INTERVAL 5
#define CACHE_CLEAN_INTERVAL 60
+static int cache_on = 1;
+static unsigned cache_stat_timeout = DEFAULT_CACHE_TIMEOUT;
+static unsigned cache_dir_timeout = DEFAULT_CACHE_TIMEOUT;
+static unsigned cache_link_timeout = DEFAULT_CACHE_TIMEOUT;
+
struct node {
struct stat stat;
time_t stat_valid;
@@ -136,7 +144,7 @@ static void cache_add_attr(const char *path, const struct stat *stbuf)
node = cache_get(path);
now = time(NULL);
node->stat = *stbuf;
- node->stat_valid = time(NULL) + CACHE_TIMEOUT;
+ node->stat_valid = time(NULL) + cache_stat_timeout;
if (node->stat_valid > node->valid)
node->valid = node->stat_valid;
cache_clean();
@@ -153,7 +161,7 @@ static void cache_add_dir(const char *path, char **dir)
now = time(NULL);
g_strfreev(node->dir);
node->dir = dir;
- node->dir_valid = time(NULL) + CACHE_TIMEOUT;
+ node->dir_valid = time(NULL) + cache_dir_timeout;
if (node->dir_valid > node->valid)
node->valid = node->dir_valid;
cache_clean();
@@ -177,7 +185,7 @@ static void cache_add_link(const char *path, const char *link, size_t size)
now = time(NULL);
g_free(node->link);
node->link = g_strndup(link, my_strnlen(link, size-1));
- node->link_valid = time(NULL) + CACHE_TIMEOUT;
+ node->link_valid = time(NULL) + cache_link_timeout;
if (node->link_valid > node->valid)
node->valid = node->link_valid;
cache_clean();
@@ -280,6 +288,22 @@ static int cache_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
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 next_oper->cache_getdir(path, &ch, cache_unity_dirfill);
+}
+
static int cache_mknod(const char *path, mode_t mode, dev_t rdev)
{
int err = next_oper->oper.mknod(path, mode, rdev);
@@ -379,40 +403,134 @@ static int cache_write(const char *path, const char *buf, size_t size,
return res;
}
+static void cache_unity_fill(struct fuse_cache_operations *oper,
+ struct fuse_operations *cache_oper)
+{
+ cache_oper->getattr = oper->oper.getattr;
+ 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;
+}
+
struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
{
static struct fuse_operations cache_oper;
next_oper = 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 : oper->oper.getdir;
- 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.open = oper->oper.open;
- cache_oper.read = oper->oper.read;
- cache_oper.write = oper->oper.write ? cache_write : NULL;
- cache_oper.statfs = oper->oper.statfs;
- cache_oper.release = oper->oper.release;
- cache_oper.fsync = oper->oper.fsync;
- cache_oper.setxattr = oper->oper.setxattr;
- cache_oper.getxattr = oper->oper.getxattr;
- cache_oper.listxattr = oper->oper.listxattr;
- cache_oper.removexattr = oper->oper.removexattr;
- pthread_mutex_init(&cache_lock, NULL);
- cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_node);
- if (cache == NULL) {
- fprintf(stderr, "failed to create cache\n");
- return NULL;
+ cache_unity_fill(oper, &cache_oper);
+ if (cache_on) {
+ 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;
+ pthread_mutex_init(&cache_lock, NULL);
+ cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ free_node);
+ if (cache == NULL) {
+ fprintf(stderr, "failed to create cache\n");
+ return NULL;
+ }
}
return &cache_oper;
}
+
+enum {
+ COPT_CACHE,
+ COPT_TIMEOUT,
+ COPT_STAT_TIMEOUT,
+ COPT_DIR_TIMEOUT,
+ COPT_LINK_TIMEOUT,
+ COPT_LAST /* Last entry in this list! */
+};
+
+static struct opt cache_opts[] = {
+ [COPT_CACHE] = { .optname = "cache" },
+ [COPT_TIMEOUT] = { .optname = "cache_timeout" },
+ [COPT_STAT_TIMEOUT] = { .optname = "cache_stat_timeout" },
+ [COPT_DIR_TIMEOUT] = { .optname = "cache_dir_timeout" },
+ [COPT_LINK_TIMEOUT] = { .optname = "cache_link_timeout" },
+ [COPT_LAST] = { .optname = NULL }
+};
+
+static int get_timeout(int sel, unsigned *timeoutp)
+{
+ char *end;
+ struct opt *o = &cache_opts[sel];
+ unsigned val;
+ if (!o->present)
+ return 0;
+ if (!o->value || !o->value[0]) {
+ fprintf(stderr, "Missing value for '%s' option\n", o->optname);
+ return -1;
+ }
+ val = strtoul(o->value, &end, 10);
+ if (end[0]) {
+ fprintf(stderr, "Invalid value for '%s' option\n", o->optname);
+ return -1;
+ }
+ *timeoutp = val;
+ return 1;
+}
+
+int cache_parse_options(int *argcp, char *argv[])
+{
+ unsigned timeout;
+ int res;
+ process_options(argcp, argv, cache_opts, 1);
+ if (cache_opts[COPT_CACHE].present) {
+ char *val = cache_opts[COPT_CACHE].value;
+ if (!val || !val[0] ||
+ (strcmp(val, "yes") != 0 && strcmp(val, "no") != 0)) {
+ fprintf(stderr, "Invalid or missing value for 'cache' option\n");
+ return -1;
+ }
+ if (strcmp(val, "yes") == 0)
+ cache_on = 1;
+ else
+ cache_on = 0;
+ }
+ if ((res = get_timeout(COPT_TIMEOUT, &timeout)) == -1)
+ return -1;
+ if (res == 1) {
+ cache_stat_timeout = timeout;
+ cache_dir_timeout = timeout;
+ cache_link_timeout = timeout;
+ }
+ if(get_timeout(COPT_STAT_TIMEOUT, &cache_stat_timeout) == -1 ||
+ get_timeout(COPT_DIR_TIMEOUT, &cache_dir_timeout) == -1 ||
+ get_timeout(COPT_LINK_TIMEOUT, &cache_link_timeout) == -1)
+ return -1;
+ return 0;
+}
diff --git a/cache.h b/cache.h
index 1466a1b..0f9d4f4 100644
--- a/cache.h
+++ b/cache.h
@@ -19,3 +19,4 @@ struct fuse_cache_operations {
};
struct fuse_operations *cache_init(struct fuse_cache_operations *oper);
+int cache_parse_options(int *argcp, char *argv[]);
diff --git a/sshfs.c b/sshfs.c
index 59c95cb..b58d156 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -1163,16 +1163,19 @@ static void usage(const char *progname)
const char *fusehelp[] = { progname, "-ho", NULL };
fprintf(stderr,
- "usage: %s [user@]host:[dir]] mountpoint [options]\n"
- "\n"
- "SSHFS Options:\n"
- " -V show version information\n"
- " -p PORT equivalent to '-o port=PORT'\n"
- " -C equivalent to '-o compression=yes'\n"
- " -o ssh_command=CMD execute CMD instead of 'ssh'\n"
- " -o directport=PORT directly connect to port bypassing ssh\n"
- " -o SSHOPT=VAL ssh options (see man ssh_config)\n"
- "\n", progname);
+"usage: %s [user@]host:[dir]] mountpoint [options]\n"
+"\n"
+"SSHFS Options:\n"
+" -V show version information\n"
+" -p PORT equivalent to '-o port=PORT'\n"
+" -C equivalent to '-o compression=yes'\n"
+" -o cache=YESNO Enable caching {yes,no} (default: yes)\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 ssh_command=CMD execute CMD instead of 'ssh'\n"
+" -o directport=PORT directly connect to PORT bypassing ssh\n"
+" -o SSHOPT=VAL ssh options (see man ssh_config)\n"
+"\n", progname);
fuse_main(2, (char **) fusehelp, &sshfs_oper.oper);
exit(1);
}
@@ -1257,6 +1260,10 @@ int main(int argc, char *argv[])
if (res == -1)
exit(1);
+ res = cache_parse_options(&newargc, newargv);
+ if (res == -1)
+ exit(1);
+
newargv[newargc++] = "-omax_read=65536";
newargv[newargc++] = g_strdup_printf("-ofsname=sshfs#%s", fsname);
g_free(fsname);