patch-2.4.19 linux-2.4.19/fs/nfs/dir.c
Next file: linux-2.4.19/fs/nfs/flushd.c
Previous file: linux-2.4.19/fs/namespace.c
Back to the patch index
Back to the overall index
- Lines: 270
- Date:
Fri Aug 2 17:39:45 2002
- Orig file:
linux-2.4.18/fs/nfs/dir.c
- Orig date:
Tue Jun 12 11:15:08 2001
diff -urN linux-2.4.18/fs/nfs/dir.c linux-2.4.19/fs/nfs/dir.c
@@ -402,6 +402,21 @@
}
/*
+ * A check for whether or not the parent directory has changed.
+ * In the case it has, we assume that the dentries are untrustworthy
+ * and may need to be looked up again.
+ */
+static inline
+int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+{
+ if (IS_ROOT(dentry))
+ return 1;
+ if (nfs_revalidate_inode(NFS_SERVER(dir), dir))
+ return 0;
+ return time_after(dentry->d_time, NFS_MTIME_UPDATE(dir));
+}
+
+/*
* Whenever an NFS operation succeeds, we know that the dentry
* is valid, so we update the revalidation timestamp.
*/
@@ -410,48 +425,31 @@
dentry->d_time = jiffies;
}
-static inline int nfs_dentry_force_reval(struct dentry *dentry, int flags)
+static inline
+int nfs_lookup_verify_inode(struct inode *inode, int flags)
{
- struct inode *inode = dentry->d_inode;
- unsigned long timeout = NFS_ATTRTIMEO(inode);
-
+ struct nfs_server *server = NFS_SERVER(inode);
/*
- * If it's the last lookup in a series, we use a stricter
- * cache consistency check by looking at the parent mtime.
- *
- * If it's been modified in the last hour, be really strict.
- * (This still means that we can avoid doing unnecessary
- * work on directories like /usr/share/bin etc which basically
- * never change).
+ * If we're interested in close-to-open cache consistency,
+ * then we revalidate the inode upon lookup.
*/
- if (!(flags & LOOKUP_CONTINUE)) {
- long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
-
- if (diff < 15*60)
- timeout = 0;
- }
-
- return time_after(jiffies,dentry->d_time + timeout);
+ if (!(server->flags & NFS_MOUNT_NOCTO) && !(flags & LOOKUP_CONTINUE))
+ NFS_CACHEINV(inode);
+ return nfs_revalidate_inode(server, inode);
}
/*
* We judge how long we want to trust negative
* dentries by looking at the parent inode mtime.
*
- * If mtime is close to present time, we revalidate
- * more often.
+ * If parent mtime has changed, we revalidate, else we wait for a
+ * period corresponding to the parent's attribute cache timeout value.
*/
-#define NFS_REVALIDATE_NEGATIVE (1 * HZ)
-static inline int nfs_neg_need_reval(struct dentry *dentry)
+static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
{
- struct inode *dir = dentry->d_parent->d_inode;
- unsigned long timeout = NFS_ATTRTIMEO(dir);
- long diff = CURRENT_TIME - dir->i_mtime;
-
- if (diff < 5*60 && timeout > NFS_REVALIDATE_NEGATIVE)
- timeout = NFS_REVALIDATE_NEGATIVE;
-
- return time_after(jiffies, dentry->d_time + timeout);
+ if (!nfs_check_verifier(dir, dentry))
+ return 1;
+ return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
}
/*
@@ -462,9 +460,8 @@
* NOTE! The hit can be a negative hit too, don't assume
* we have an inode!
*
- * If the dentry is older than the revalidation interval,
- * we do a new lookup and verify that the dentry is still
- * correct.
+ * If the parent directory is seen to have changed, we throw out the
+ * cached dentry and do a new lookup.
*/
static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
{
@@ -477,13 +474,9 @@
lock_kernel();
dir = dentry->d_parent->d_inode;
inode = dentry->d_inode;
- /*
- * If we don't have an inode, let's look at the parent
- * directory mtime to get a hint about how often we
- * should validate things..
- */
+
if (!inode) {
- if (nfs_neg_need_reval(dentry))
+ if (nfs_neg_need_reval(dir, dentry))
goto out_bad;
goto out_valid;
}
@@ -494,48 +487,39 @@
goto out_bad;
}
- if (!nfs_dentry_force_reval(dentry, flags))
+ /* Force a full look up iff the parent directory has changed */
+ if (nfs_check_verifier(dir, dentry)) {
+ if (nfs_lookup_verify_inode(inode, flags))
+ goto out_bad;
goto out_valid;
-
- if (IS_ROOT(dentry)) {
- __nfs_revalidate_inode(NFS_SERVER(inode), inode);
- goto out_valid_renew;
}
- /*
- * Do a new lookup and check the dentry attributes.
- */
+ if (NFS_STALE(inode))
+ goto out_bad;
+
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error)
goto out_bad;
-
- /* Inode number matches? */
- if (!(fattr.valid & NFS_ATTR_FATTR) ||
- NFS_FSID(inode) != fattr.fsid ||
- NFS_FILEID(inode) != fattr.fileid)
+ if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
goto out_bad;
-
- /* Ok, remember that we successfully checked it.. */
- nfs_refresh_inode(inode, &fattr);
-
- if (nfs_inode_is_stale(inode, &fhandle, &fattr))
+ if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
goto out_bad;
- out_valid_renew:
nfs_renew_times(dentry);
-out_valid:
+ out_valid:
unlock_kernel();
return 1;
-out_bad:
- shrink_dcache_parent(dentry);
- /* If we have submounts, don't unhash ! */
- if (have_submounts(dentry))
- goto out_valid;
- d_drop(dentry);
- /* Purge readdir caches. */
- nfs_zap_caches(dir);
- if (inode && S_ISDIR(inode->i_mode))
+ out_bad:
+ NFS_CACHEINV(dir);
+ if (inode && S_ISDIR(inode->i_mode)) {
+ /* Purge readdir caches. */
nfs_zap_caches(inode);
+ /* If we have submounts, don't unhash ! */
+ if (have_submounts(dentry))
+ goto out_valid;
+ shrink_dcache_parent(dentry);
+ }
+ d_drop(dentry);
unlock_kernel();
return 0;
}
@@ -568,6 +552,8 @@
nfs_complete_unlink(dentry);
unlock_kernel();
}
+ if (is_bad_inode(inode))
+ force_delete(inode);
iput(inode);
}
@@ -604,9 +590,9 @@
if (inode) {
no_entry:
d_add(dentry, inode);
- nfs_renew_times(dentry);
error = 0;
}
+ nfs_renew_times(dentry);
}
out:
return ERR_PTR(error);
@@ -621,6 +607,12 @@
struct inode *inode;
int error = -EACCES;
+ if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
+ struct inode *dir = dentry->d_parent->d_inode;
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+ if (error)
+ goto out_err;
+ }
inode = nfs_fhget(dentry, fhandle, fattr);
if (inode) {
d_instantiate(dentry, inode);
@@ -628,6 +620,9 @@
error = 0;
}
return error;
+out_err:
+ d_drop(dentry);
+ return error;
}
/*
@@ -658,9 +653,9 @@
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
&attr, 0, &fhandle, &fattr);
- if (!error && fhandle.size != 0)
+ if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
- if (error || fhandle.size == 0)
+ else
d_drop(dentry);
return error;
}
@@ -684,9 +679,9 @@
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
&fhandle, &fattr);
- if (!error && fhandle.size != 0)
+ if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
- if (error || fhandle.size == 0)
+ else
d_drop(dentry);
return error;
}
@@ -719,9 +714,9 @@
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
&fattr);
- if (!error && fhandle.size != 0)
+ if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
- if (error || fhandle.size == 0)
+ else
d_drop(dentry);
return error;
}
@@ -926,7 +921,7 @@
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
&attr, &sym_fh, &sym_attr);
- if (!error && sym_fh.size != 0 && (sym_attr.valid & NFS_ATTR_FATTR)) {
+ if (!error) {
error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
} else {
if (error == -EEXIST)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)