summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2004-07-09 08:58:32 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2004-07-09 08:58:32 +0000
commitfbbb47a3081ff829ca728a66250169c373b961da (patch)
treedbdbe015f1a72682578f743248f2677b11160974
parent9b53489a21e8c3ab45c43bcb7c62e0ee25898281 (diff)
downloadfuse-fbbb47a3081ff829ca728a66250169c373b961da.tar.gz
attribute caching fix
-rw-r--r--ChangeLog6
-rw-r--r--kernel/dir.c25
2 files changed, 30 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 0476313..dee4a83 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-08 Miklos Szeredi <miklos@szeredi.hu>
+
+ * When performing create or remove operation, refresh the parent's
+ attributes on next revalidate, as i_nlink (and maybe size/time)
+ could be inacurate.
+
2004-07-06 Miklos Szeredi <miklos@szeredi.hu>
* Make RELEASE method synchronous. This fixes an abort in libfuse
diff --git a/kernel/dir.c b/kernel/dir.c
index e6bf28c..9a88a23 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -145,6 +145,17 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
return 0;
}
+static void uncache_dir(struct inode *dir)
+{
+ struct dentry *entry = d_find_alias(dir);
+ if (!entry)
+ dir->i_nlink = 0;
+ else {
+ entry->d_time = jiffies - FUSE_REVALIDATE_TIME - 1;
+ dput(entry);
+ }
+}
+
/* create needs to return a positive entry, so this is actually an
mknod+lookup */
static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
@@ -188,6 +199,7 @@ static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
}
d_instantiate(entry, inode);
+ uncache_dir(dir);
return 0;
}
@@ -208,6 +220,7 @@ static int lookup_new_entry(struct inode *dir, struct dentry *entry)
return err ? err : -ENOENT;
}
d_instantiate(entry, inode);
+ uncache_dir(dir);
return 0;
}
@@ -286,6 +299,8 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
err = fuse_do_getattr(entry->d_inode);
if(err == -ENOENT)
entry->d_inode->i_nlink = 0;
+
+ uncache_dir(dir);
return 0;
}
return err;
@@ -294,8 +309,10 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
int err = fuse_remove(dir, entry, FUSE_RMDIR);
- if(!err)
+ if(!err) {
entry->d_inode->i_nlink = 0;
+ uncache_dir(dir);
+ }
return err;
}
@@ -321,6 +338,12 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
in.args[2].value = newent->d_name.name;
request_send(fc, &in, &out);
+ if (!out.h.error) {
+ uncache_dir(olddir);
+ if (olddir != newdir)
+ uncache_dir(newdir);
+ }
+
return out.h.error;
}