From 891b874eedcc9f49364d12b4773e01a8b013fb67 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 29 Jul 2004 09:27:49 +0000 Subject: [PATCH] add fuse_invalidate() to library API --- ChangeLog | 4 +++ example/hello.c | 10 +++++++- include/fuse.h | 10 ++++++++ kernel/dev.c | 4 ++- lib/fuse.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e64b898..085a01f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-07-29 Miklos Szeredi + + * Add fuse_invalidate() to library API + 2004-07-26 Miklos Szeredi * Check permissions in setattr if 'default_permissions' flag is diff --git a/example/hello.c b/example/hello.c index da2a9ee..040c835 100644 --- a/example/hello.c +++ b/example/hello.c @@ -60,10 +60,18 @@ static int hello_open(const char *path, int flags) static int hello_read(const char *path, char *buf, size_t size, off_t offset) { + size_t len; if(strcmp(path, hello_path) != 0) return -ENOENT; - memcpy(buf, hello_str + offset, size); + len = strlen(hello_str); + if (offset < len) { + if (offset + size > len) + size = len - offset; + memcpy(buf, hello_str + offset, size); + } else + size = 0; + return size; } diff --git a/include/fuse.h b/include/fuse.h index 726b681..845e645 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -171,6 +171,16 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op); */ struct fuse *fuse_get(void); +/** + * Invalidate cached data of a file. + * + * Useful if the 'kernel_cache' mount option is given, since in that + * case the cache is not invalidated on file open. + * + * @return 0 on success or -errno on failure + */ +int fuse_invalidate(struct fuse *f, const char *path); + /* ----------------------------------------------------------- * * More detailed API * * ----------------------------------------------------------- */ diff --git a/kernel/dev.c b/kernel/dev.c index a12820d..07c19ee 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -422,6 +422,7 @@ static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) struct inode *inode = ilookup(fc->sb, uh->ino); if (!inode) return -ENOENT; + fuse_sync_inode(inode); invalidate_inode_pages(inode->i_mapping); iput(inode); return 0; @@ -433,6 +434,7 @@ static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) int err = -ENOENT; if (inode) { if (INO_FI(inode)) { + fuse_sync_inode(inode); invalidate_inode_pages(inode); err = 0; } @@ -453,7 +455,7 @@ static int fuse_user_request(struct fuse_conn *fc, const char *buf, return -EINVAL; } - if (copy_from_user(&uh, buf, sizeof(struct fuse_out_header))) + if (copy_from_user(&uh, buf, sizeof(struct fuse_user_header))) return -EFAULT; switch (uh.opcode) { diff --git a/lib/fuse.c b/lib/fuse.c index 80c1488..671fbcc 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -225,6 +225,37 @@ static struct node *find_node(struct fuse *f, fino_t parent, char *name, return node; } +static int path_lookup(struct fuse *f, const char *path, fino_t *inop) +{ + fino_t ino; + int err; + char *s; + char *name; + char *tmp = strdup(path); + if (!tmp) + return -ENOMEM; + + pthread_mutex_lock(&f->lock); + ino = FUSE_ROOT_INO; + err = 0; + for (s = tmp; (name = strsep(&s, "/")) != NULL; ) { + if (name[0]) { + struct node *node = __lookup_node(f, ino, name); + if (node == NULL) { + err = -ENOENT; + break; + } + ino = node->ino; + } + } + pthread_mutex_unlock(&f->lock); + free(tmp); + if (!err) + *inop = ino; + + return err; +} + static char *add_name(char *buf, char *s, const char *name) { size_t len = strlen(name); @@ -1544,6 +1575,40 @@ void fuse_loop(struct fuse *f) } } +int fuse_invalidate(struct fuse *f, const char *path) +{ + int res; + int err; + fino_t ino; + struct fuse_user_header h; + + err = path_lookup(f, path, &ino); + if (err) { + if (err == -ENOENT) + return 0; + else + return err; + } + + memset(&h, 0, sizeof(struct fuse_user_header)); + h.opcode = FUSE_INVALIDATE; + h.ino = ino; + + if ((f->flags & FUSE_DEBUG)) { + printf("INVALIDATE ino: %li\n", ino); + fflush(stdout); + } + + res = write(f->fd, &h, sizeof(struct fuse_user_header)); + if (res == -1) { + if (errno != ENOENT) { + perror("fuse: writing device"); + return -errno; + } + } + return 0; +} + void fuse_exit(struct fuse *f) { f->exited = 1; -- 2.30.2