aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--include/linux/fuse.h20
-rw-r--r--kernel/dev.c4
-rw-r--r--kernel/dir.c49
-rw-r--r--kernel/fuse_i.h5
-rw-r--r--lib/fuse.c33
6 files changed, 75 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index f2325b9..051ab94 100644
--- 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()
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 834c1be..d5fd357 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -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;
};
diff --git a/kernel/dev.c b/kernel/dev.c
index 43af356..f0733d0 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -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);
}
diff --git a/kernel/dir.c b/kernel/dir.c
index c5810e9..4051d07 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -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;
}
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 48e52c9..2443efe 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -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
diff --git a/lib/fuse.c b/lib/fuse.c
index 9d0783d..27e331a 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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);