patch-2.1.120 linux/fs/nfs/dir.c
Next file: linux/fs/nfs/write.c
Previous file: linux/fs/lockd/svc.c
Back to the patch index
Back to the overall index
- Lines: 250
- Date:
Fri Sep 4 09:39:24 1998
- Orig file:
v2.1.119/linux/fs/nfs/dir.c
- Orig date:
Wed Aug 26 11:37:41 1998
diff -u --recursive --new-file v2.1.119/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
@@ -29,11 +29,6 @@
#include <asm/segment.h> /* for fs functions */
-#define NFS_MAX_AGE 10*HZ /* max age for dentry validation */
-
-/* needed by smbfs as well ... move to dcache? */
-extern void nfs_renew_times(struct dentry *);
-
#define NFS_PARANOIA 1
/* #define NFS_DEBUG_VERBOSE 1 */
@@ -376,6 +371,7 @@
nfs_invalidate_dircache_sb(NULL);
}
+#define NFS_REVALIDATE_INTERVAL (5*HZ)
/*
* This is called every time the dcache has a lookup hit,
* and we should check whether we can really trust that
@@ -384,36 +380,69 @@
* NOTE! The hit can be a negative hit too, don't assume
* we have an inode!
*
- * The decision to drop the dentry should probably be
- * smarter than this. Right now we believe in directories
- * for 10 seconds, and in normal files for five..
+ * If the dentry is older than the revalidation interval,
+ * we do a new lookup and verify that the dentry is still
+ * correct.
*/
static int nfs_lookup_revalidate(struct dentry * dentry)
{
+ struct dentry * parent = dentry->d_parent;
+ struct inode * inode = dentry->d_inode;
unsigned long time = jiffies - dentry->d_time;
- unsigned long max = 5*HZ;
+ int error;
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
- if (dentry->d_inode) {
- if (is_bad_inode(dentry->d_inode)) {
+ if (inode && is_bad_inode(inode)) {
#ifdef NFS_PARANOIA
printk("nfs_lookup_validate: %s/%s has dud inode\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
+parent->d_name.name, dentry->d_name.name);
#endif
- goto bad;
- }
- if (S_ISDIR(dentry->d_inode->i_mode))
- max = NFS_MAX_AGE;
+ goto out_bad;
}
- return (time < max) || IS_ROOT(dentry);
-bad:
+ if (time < NFS_REVALIDATE_INTERVAL)
+ goto out_valid;
+ /*
+ * Don't bother looking up a negative dentry ...
+ */
+ if (!inode)
+ goto out_bad;
+
+ if (IS_ROOT(dentry))
+ goto out_valid;
+ /*
+ * Do a new lookup and check the dentry attributes.
+ */
+ error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent),
+ dentry->d_name.name, &fhandle, &fattr);
+ if (error) {
+printk("nfs_lookup_revalidate: error=%d\n", error);
+ goto out_bad;
+ }
+
+ /* Inode number matches? */
+ if (fattr.fileid != inode->i_ino) {
+printk("nfs_lookup_revalidate: %s/%s inode mismatch, old=%ld, new=%u\n",
+parent->d_name.name, dentry->d_name.name, inode->i_ino, fattr.fileid);
+ goto out_bad;
+ }
+ /* Filehandle matches? */
+ if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
+printk("nfs_lookup_revalidate: %s/%s fh changed\n",
+parent->d_name.name, dentry->d_name.name);
+ goto out_bad;
+ }
+
+out_valid:
+ return 1;
+out_bad:
return 0;
}
/*
* This is called from dput() when d_count is going to 0.
- * We use it to clean up silly-renamed files, and to check
- * for dentries that have already expired.
+ * We use it to clean up silly-renamed files.
*/
static void nfs_dentry_delete(struct dentry *dentry)
{
@@ -433,14 +462,6 @@
dentry->d_parent->d_name.name,
dentry->d_name.name, error);
}
- /*
- * Check whether to expire the dentry ...
- */
- else {
- unsigned long age = jiffies - dentry->d_time;
- if (age > NFS_MAX_AGE)
- d_drop(dentry);
- }
#ifdef NFS_PARANOIA
/*
@@ -523,17 +544,12 @@
#endif
/*
- * Whenever a lookup succeeds, we know the parent directories
- * are all valid, so we want to update the dentry timestamps.
+ * Whenever an NFS operation succeeds, we know that the dentry
+ * is valid, so we update the revalidation timestamp.
*/
-void nfs_renew_times(struct dentry * dentry)
+static inline void nfs_renew_times(struct dentry * dentry)
{
- for (;;) {
- dentry->d_time = jiffies;
- if (dentry == dentry->d_parent)
- break;
- dentry = dentry->d_parent;
- }
+ dentry->d_time = jiffies;
}
static int nfs_lookup(struct inode *dir, struct dentry * dentry)
@@ -546,11 +562,6 @@
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_lookup: inode is NULL or not a directory\n");
- return -ENOENT;
- }
-
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
goto out;
@@ -635,12 +646,7 @@
struct nfs_fh fhandle;
dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_create: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
@@ -675,12 +681,7 @@
struct nfs_fh fhandle;
dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_mknod: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
if (dentry->d_name.len > NFS_MAXNAMLEN)
return -ENAMETOOLONG;
@@ -712,12 +713,7 @@
struct nfs_fh fhandle;
dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_mkdir: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
@@ -754,12 +750,7 @@
int error, rehash = 0;
dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_rmdir: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
@@ -1010,12 +1001,7 @@
int error;
dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_unlink: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
@@ -1039,12 +1025,7 @@
int error;
dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_symlink: inode is NULL or not a directory\n");
- return -ENOENT;
- }
+ dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
@@ -1095,11 +1076,6 @@
dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
dentry->d_parent->d_name.name, dentry->d_name.name);
-
- if (!dir || !S_ISDIR(dir->i_mode)) {
- printk("nfs_link: dir is NULL or not a directory\n");
- return -ENOENT;
- }
error = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_MAXNAMLEN)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov