kernel interface changes
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 2 Mar 2004 11:11:24 +0000 (11:11 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 2 Mar 2004 11:11:24 +0000 (11:11 +0000)
ChangeLog
include/linux/fuse.h
kernel/dev.c
kernel/dir.c
kernel/fuse_i.h
lib/fuse.c

index f2325b9a48ab57e96f4847c238709bcd0db588d2..051ab946e621223f34e1af2e702263b9e4eb14c7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-03-02  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * More kernel interface changes:
+
+       * Lookup/getattr return cache timeout values
+
 2004-02-25  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * Clean up option parsing in fuse_main()
index 834c1be1cac8a56e9020dfc177f3187e82b1cd13..d5fd35781e6b8fc21b08e35f294b58b0a73caa41 100644 (file)
@@ -119,9 +119,14 @@ enum fuse_opcode {
 /* Conservative buffer size for the client */
 #define FUSE_MAX_IN 8192
 
-struct fuse_lookup_out {
-       unsigned long ino;
-       unsigned long generation;
+struct fuse_entry_out {
+       unsigned long ino;         /* Inode number */
+       unsigned long generation;  /* Inode generation: ino:gen must
+                                      be unique for the fs's lifetime */
+       unsigned long entry_valid; /* Cache timeout for the name */
+       unsigned long entry_valid_nsec;
+       unsigned long attr_valid;  /* Cache timeout for the attributes */
+       unsigned long attr_valid_nsec;
        struct fuse_attr attr;
 };
 
@@ -129,13 +134,14 @@ struct fuse_forget_in {
        int version;
 };
 
-struct fuse_getattr_out {
+struct fuse_attr_out {
+       unsigned long attr_valid;  /* Cache timeout for the attributes */
+       unsigned long attr_valid_nsec;
        struct fuse_attr attr;
 };
 
 struct fuse_getdir_out {
        int fd;
-       void *file; /* Used by kernel only */
 };
 
 struct fuse_mknod_in {
@@ -160,10 +166,6 @@ struct fuse_setattr_in {
        unsigned int valid;
 };
 
-struct fuse_setattr_out {
-       struct fuse_attr attr;
-};
-
 struct fuse_open_in {
        unsigned int flags;
 };
index 43af356aaee3340d8849c47bea75b1ca03327041..f0733d006c262880d9eb5b965cc98090282f53cd 100644 (file)
@@ -334,8 +334,8 @@ static struct fuse_req *request_find(struct fuse_conn *fc, unsigned int unique)
 
 static void process_getdir(struct fuse_req *req)
 {
-       struct fuse_getdir_out *arg;
-       arg = (struct fuse_getdir_out *) req->out->args[0].value;
+       struct fuse_getdir_out_i *arg;
+       arg = (struct fuse_getdir_out_i *) req->out->args[0].value;
        arg->file = fget(arg->fd);
 }
 
index c5810e97aa2d624f8677f153336f355424cba804..4051d07389cd7d3913d874c1d21103fe0970a64c 100644 (file)
@@ -20,9 +20,6 @@ static struct file_operations fuse_dir_operations;
 
 static struct dentry_operations fuse_dentry_operations;
 
-/* FIXME: This should be user configurable */
-#define FUSE_REVALIDATE_TIME (1 * HZ)
-
 #ifndef KERNEL_2_6
 #define new_decode_dev(x) (x)
 #define new_encode_dev(x) (x)
@@ -106,7 +103,7 @@ struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation,
 }
 
 static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
-                         struct fuse_lookup_out *outarg, int *version)
+                         struct fuse_entry_out *outarg, int *version)
 {
        struct fuse_conn *fc = INO_FC(dir);
        struct fuse_in in = FUSE_IN_INIT;
@@ -118,7 +115,7 @@ static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
        in.args[0].size = entry->d_name.len + 1;
        in.args[0].value = entry->d_name.name;
        out.numargs = 1;
-       out.args[0].size = sizeof(struct fuse_lookup_out);
+       out.args[0].size = sizeof(struct fuse_entry_out);
        out.args[0].value = outarg;
        request_send(fc, &in, &out);
 
@@ -126,11 +123,21 @@ static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
        return out.h.error;
 }
 
+static inline unsigned long time_to_jiffies(unsigned long sec,
+                                           unsigned long nsec)
+{
+       /* prevent wrapping of jiffies */
+       if(sec + 1 >= LONG_MAX / HZ)
+               return 0;
+       
+       return jiffies + sec * HZ + nsec / (1000000000 / HZ);
+}
+
 static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
                            struct inode **inodep)
 {
        int err;
-       struct fuse_lookup_out outarg;
+       struct fuse_entry_out outarg;
        int version;
        struct inode *inode = NULL;
 
@@ -143,14 +150,15 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
        } else if(err != -ENOENT)
                return err;
 
-       entry->d_time = jiffies;
+       entry->d_time = time_to_jiffies(outarg.entry_valid,
+                                       outarg.entry_valid_nsec);
        entry->d_op = &fuse_dentry_operations;
        *inodep = inode;
        return 0;
 }
 
 static int lookup_new_entry(struct inode *dir, struct dentry *entry,
-                                  struct fuse_lookup_out *outarg, int version,
+                                  struct fuse_entry_out *outarg, int version,
                                   int mode)
 {
        struct inode *inode;
@@ -178,7 +186,7 @@ static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_mknod_in inarg;
-       struct fuse_lookup_out outarg;
+       struct fuse_entry_out outarg;
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
@@ -214,7 +222,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_mkdir_in inarg;
-       struct fuse_lookup_out outarg;
+       struct fuse_entry_out outarg;
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
@@ -242,7 +250,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
        struct fuse_conn *fc = INO_FC(dir);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
-       struct fuse_lookup_out outarg;
+       struct fuse_entry_out outarg;
 
        in.h.opcode = FUSE_SYMLINK;
        in.h.ino = dir->i_ino;
@@ -336,7 +344,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_link_in inarg;
-       struct fuse_lookup_out outarg;
+       struct fuse_entry_out outarg;
        
        memset(&inarg, 0, sizeof(inarg));
        inarg.newdir = newdir->i_ino;
@@ -366,7 +374,7 @@ int fuse_do_getattr(struct inode *inode)
        struct fuse_conn *fc = INO_FC(inode);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
-       struct fuse_getattr_out arg;
+       struct fuse_attr_out arg;
        
        in.h.opcode = FUSE_GETATTR;
        in.h.ino = inode->i_ino;
@@ -390,7 +398,7 @@ static int fuse_revalidate(struct dentry *entry)
                if(!(fc->flags & FUSE_ALLOW_OTHER) &&
                   current->fsuid != fc->uid)
                        return -EACCES;
-       } else if(time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
+       } else if(!entry->d_time || time_before_eq(jiffies, entry->d_time))
                return 0;
 
        return fuse_do_getattr(inode);
@@ -541,12 +549,12 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
        struct fuse_conn *fc = INO_FC(inode);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
-       struct fuse_getdir_out outarg;
+       struct fuse_getdir_out_i outarg;
 
        in.h.opcode = FUSE_GETDIR;
        in.h.ino = inode->i_ino;
        out.numargs = 1;
-       out.args[0].size = sizeof(outarg);
+       out.args[0].size = sizeof(struct fuse_getdir_out);
        out.args[0].value = &outarg;
        request_send(fc, &in, &out);
        if(!out.h.error) {
@@ -617,7 +625,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_setattr_in inarg;
-       struct fuse_setattr_out outarg;
+       struct fuse_attr_out outarg;
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.valid = iattr_to_fattr(attr, &inarg.attr);
@@ -646,9 +654,9 @@ static int _fuse_dentry_revalidate(struct dentry *entry)
 {
        if(!entry->d_inode)
                return 0;
-       else if(time_after(jiffies, entry->d_time + FUSE_REVALIDATE_TIME)) {
+       else if(entry->d_time && time_after(jiffies, entry->d_time)) {
                struct inode *inode = entry->d_inode;
-               struct fuse_lookup_out outarg;
+               struct fuse_entry_out outarg;
                int version;
                int ret;
                
@@ -662,7 +670,8 @@ static int _fuse_dentry_revalidate(struct dentry *entry)
                
                change_attributes(inode, &outarg.attr);
                inode->i_version = version;
-               entry->d_time = jiffies;
+               entry->d_time = time_to_jiffies(outarg.entry_valid,
+                                               outarg.entry_valid_nsec);
        }
        return 1;
 }
index 48e52c927c5138b98ad2110059f896946ed7acbf..2443efe8c16779d0974288223f3415ac928ce45d 100644 (file)
@@ -151,6 +151,11 @@ struct fuse_req {
        void *data;
 };
 
+struct fuse_getdir_out_i {
+       int fd;
+       void *file; /* Used by kernel only */
+};
+
 #ifdef KERNEL_2_6
 #define SB_FC(sb) ((struct fuse_conn *) (sb)->s_fs_info)
 #else
index 9d0783d57907ee882b46f950bfc8d8f4479c28de..27e331a6e9a869ee3fa222f4f5ea6c26d483a53c 100644 (file)
@@ -19,6 +19,9 @@
 #define FUSE_MAX_PATH 4096
 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
 
+#define ENTRY_REVALIDATE_TIME 1 /* sec */
+#define ATTR_REVALIDATE_TIME 1 /* sec */
+
 static const char *opname(enum fuse_opcode opcode)
 {
     switch(opcode) { 
@@ -407,7 +410,7 @@ static int send_reply(struct fuse *f, struct fuse_in_header *in, int error,
 }
 
 static int lookup_path(struct fuse *f, fino_t ino, int version,  char *name,
-                       const char *path, struct fuse_lookup_out *arg)
+                       const char *path, struct fuse_entry_out *arg)
 {
     int res;
     struct stat buf;
@@ -416,11 +419,15 @@ static int lookup_path(struct fuse *f, fino_t ino, int version,  char *name,
     if(res == 0) {
         struct node *node;
 
-        memset(arg, 0, sizeof(struct fuse_lookup_out));
+        memset(arg, 0, sizeof(struct fuse_entry_out));
         convert_stat(&buf, &arg->attr);
         node = find_node(f, ino, name, &arg->attr, version);
         arg->ino = node->ino;
         arg->generation = node->generation;
+        arg->entry_valid = ENTRY_REVALIDATE_TIME;
+        arg->entry_valid_nsec = 0;
+        arg->attr_valid = ATTR_REVALIDATE_TIME;
+        arg->attr_valid_nsec = 0;
         if(f->flags & FUSE_DEBUG) {
             printf("   INO: %li\n", arg->ino);
             fflush(stdout);
@@ -433,7 +440,7 @@ static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
 {
     int res;
     char *path;
-    struct fuse_lookup_out arg;
+    struct fuse_entry_out arg;
 
     res = -ENOENT;
     path = get_path_name(f, in->ino, name);
@@ -465,7 +472,7 @@ static void do_getattr(struct fuse *f, struct fuse_in_header *in)
     int res;
     char *path;
     struct stat buf;
-    struct fuse_getattr_out arg;
+    struct fuse_attr_out arg;
 
     res = -ENOENT;
     path = get_path(f, in->ino);
@@ -477,7 +484,9 @@ static void do_getattr(struct fuse *f, struct fuse_in_header *in)
     }
 
     if(res == 0) {
-        memset(&arg, 0, sizeof(struct fuse_getattr_out));
+        memset(&arg, 0, sizeof(struct fuse_attr_out));
+        arg.attr_valid = ATTR_REVALIDATE_TIME;
+        arg.attr_valid_nsec = 0;
         convert_stat(&buf, &arg.attr);
     }
 
@@ -541,7 +550,7 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in,
     char *path;
     int valid = arg->valid;
     struct fuse_attr *attr = &arg->attr;
-    struct fuse_setattr_out outarg;
+    struct fuse_attr_out outarg;
 
     res = -ENOENT;
     path = get_path(f, in->ino);
@@ -562,7 +571,9 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in,
                 struct stat buf;
                 res = f->op.getattr(path, &buf);
                 if(!res) {
-                    memset(&outarg, 0, sizeof(struct fuse_setattr_out));
+                    memset(&outarg, 0, sizeof(struct fuse_attr_out));
+                    outarg.attr_valid = ATTR_REVALIDATE_TIME;
+                    outarg.attr_valid_nsec = 0;
                     convert_stat(&buf, &outarg.attr);
                 }
             }
@@ -622,7 +633,7 @@ static void do_mknod(struct fuse *f, struct fuse_in_header *in,
     int res;
     char *path;
     char *name = PARAM(inarg);
-    struct fuse_lookup_out outarg;
+    struct fuse_entry_out outarg;
 
     res = -ENOENT;
     path = get_path_name(f, in->ino, name);
@@ -648,7 +659,7 @@ static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
     int res;
     char *path;
     char *name = PARAM(inarg);
-    struct fuse_lookup_out outarg;
+    struct fuse_entry_out outarg;
 
     res = -ENOENT;
     path = get_path_name(f, in->ino, name);
@@ -711,7 +722,7 @@ static void do_symlink(struct fuse *f, struct fuse_in_header *in, char *name,
 {
     int res;
     char *path;
-    struct fuse_lookup_out outarg;
+    struct fuse_entry_out outarg;
 
     res = -ENOENT;
     path = get_path_name(f, in->ino, name);
@@ -766,7 +777,7 @@ static void do_link(struct fuse *f, struct fuse_in_header *in,
     char *oldpath;
     char *newpath;
     char *name = PARAM(arg);
-    struct fuse_lookup_out outarg;
+    struct fuse_entry_out outarg;
 
     res = -ENOENT;
     oldpath = get_path(f, in->ino);