aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--example/hello.c10
-rw-r--r--include/fuse.h10
-rw-r--r--kernel/dev.c4
-rw-r--r--lib/fuse.c65
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 <miklos@szeredi.hu>
+
+ * Add fuse_invalidate() to library API
+
2004-07-26 Miklos Szeredi <miklos@szeredi.hu>
* 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;