aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-05-08 19:47:22 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-05-08 19:47:22 +0000
commit3800902d3a379366d5bbe51c73b24fdd5a0e5b78 (patch)
tree3e3186ac3166ff64427b71b9fcb682980b1880c1 /kernel
parent3b206c79bf0d58475a5b898bfb8d27d052a1ac29 (diff)
downloadlibfuse-3800902d3a379366d5bbe51c73b24fdd5a0e5b78.tar.gz
fix
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dir.c25
-rw-r--r--kernel/fuse_i.h7
-rw-r--r--kernel/fuse_kernel.h4
-rw-r--r--kernel/inode.c21
4 files changed, 32 insertions, 25 deletions
diff --git a/kernel/dir.c b/kernel/dir.c
index 0912d50..078d517 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -48,7 +48,6 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 0;
else if (time_after(jiffies, entry->d_time)) {
int err;
- int version;
struct fuse_entry_out outarg;
struct inode *inode = entry->d_inode;
struct fuse_inode *fi = get_fuse_inode(inode);
@@ -59,15 +58,19 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
request_send_nonint(fc, req);
- version = req->out.h.unique;
err = req->out.h.error;
+ if (!err) {
+ if (outarg.nodeid != get_node_id(inode)) {
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
+ return 0;
+ }
+ fi->nlookup ++;
+ }
fuse_put_request(fc, req);
- if (err || outarg.nodeid != get_node_id(inode) ||
- (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
+ if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
return 0;
fuse_change_attributes(inode, &outarg.attr);
- inode->i_version = version;
entry->d_time = time_to_jiffies(outarg.entry_valid,
outarg.entry_valid_nsec);
fi->i_time = time_to_jiffies(outarg.attr_valid,
@@ -94,7 +97,6 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
struct inode **inodep)
{
int err;
- int version;
struct fuse_entry_out outarg;
struct inode *inode = NULL;
struct fuse_conn *fc = get_fuse_conn(dir);
@@ -109,13 +111,12 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
- version = req->out.h.unique;
err = req->out.h.error;
if (!err) {
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
- &outarg.attr, version);
+ &outarg.attr);
if (!inode) {
- fuse_send_forget(fc, req, outarg.nodeid, version);
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
return -ENOMEM;
}
}
@@ -154,7 +155,6 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
struct fuse_entry_out outarg;
struct inode *inode;
struct fuse_inode *fi;
- int version;
int err;
req->in.h.nodeid = get_node_id(dir);
@@ -163,16 +163,15 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
req->out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg;
request_send(fc, req);
- version = req->out.h.unique;
err = req->out.h.error;
if (err) {
fuse_put_request(fc, req);
return err;
}
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
- &outarg.attr, version);
+ &outarg.attr);
if (!inode) {
- fuse_send_forget(fc, req, outarg.nodeid, version);
+ fuse_send_forget(fc, req, outarg.nodeid, 1);
return -ENOMEM;
}
fuse_put_request(fc, req);
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 25724b4..6ba851e 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -110,6 +110,9 @@ struct fuse_inode {
* and kernel */
u64 nodeid;
+ /** Number of lookups on this inode */
+ u64 nlookup;
+
/** The request used for sending the FORGET message */
struct fuse_req *forget_req;
@@ -390,13 +393,13 @@ extern spinlock_t fuse_lock;
* Get a filled in inode
*/
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
- int generation, struct fuse_attr *attr, int version);
+ int generation, struct fuse_attr *attr);
/**
* Send FORGET command
*/
void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
- unsigned long nodeid, int version);
+ unsigned long nodeid, u64 nlookup);
/**
* Send READ or READDIR request
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index 3c06967..104d31a 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -11,7 +11,7 @@
#include <asm/types.h>
/** Version number of this interface */
-#define FUSE_KERNEL_VERSION 6
+#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 1
@@ -113,7 +113,7 @@ struct fuse_entry_out {
};
struct fuse_forget_in {
- __u64 version;
+ __u64 nlookup;
};
struct fuse_attr_out {
diff --git a/kernel/inode.c b/kernel/inode.c
index 6ef9491..4c36ad0 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -63,6 +63,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi = get_fuse_inode(inode);
fi->i_time = jiffies - 1;
fi->nodeid = 0;
+ fi->nlookup = 0;
fi->forget_req = fuse_request_alloc();
if (!fi->forget_req) {
kmem_cache_free(fuse_inode_cachep, inode);
@@ -86,10 +87,10 @@ static void fuse_read_inode(struct inode *inode)
}
void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
- unsigned long nodeid, int version)
+ unsigned long nodeid, u64 nlookup)
{
struct fuse_forget_in *inarg = &req->misc.forget_in;
- inarg->version = version;
+ inarg->nlookup = nlookup;
req->in.h.opcode = FUSE_FORGET;
req->in.h.nodeid = nodeid;
req->in.numargs = 1;
@@ -103,7 +104,7 @@ static void fuse_clear_inode(struct inode *inode)
if (inode->i_sb->s_flags & MS_ACTIVE) {
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
- fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version);
+ fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup);
fi->forget_req = NULL;
}
}
@@ -181,9 +182,10 @@ static int fuse_inode_set(struct inode *inode, void *_nodeidp)
}
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
- int generation, struct fuse_attr *attr, int version)
+ int generation, struct fuse_attr *attr)
{
struct inode *inode;
+ struct fuse_inode *fi;
struct fuse_conn *fc = get_fuse_conn_super(sb);
int retried = 0;
@@ -206,8 +208,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
goto retry;
}
+ fi = get_fuse_inode(inode);
+ fi->nlookup ++;
fuse_change_attributes(inode, attr);
- inode->i_version = version;
return inode;
}
#else
@@ -220,9 +223,10 @@ static int fuse_inode_eq(struct inode *inode, unsigned long ino, void *_nodeidp)
}
struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
- int generation, struct fuse_attr *attr, int version)
+ int generation, struct fuse_attr *attr)
{
struct inode *inode;
+ struct fuse_inode *fi;
int retried = 0;
retry:
@@ -245,8 +249,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
goto retry;
}
+ fi = get_fuse_inode(inode);
+ fi->nlookup ++;
fuse_change_attributes(inode, attr);
- inode->i_version = version;
return inode;
}
#endif
@@ -523,7 +528,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
attr.mode = mode;
attr.ino = FUSE_ROOT_ID;
- return fuse_iget(sb, 1, 0, &attr, 0);
+ return fuse_iget(sb, 1, 0, &attr);
}
#ifdef KERNEL_2_6