Re: NFS client bug introduced in 2.2.13pre14

Trond Myklebust (trond.myklebust@fys.uio.no)
01 Oct 1999 14:27:52 +0200


>>>>> " " == Patrick J LoPresti <patl@cag.lcs.mit.edu> writes:

> Or maybe pre13 or pre12; I have not been keeping track exactly.
> Anyway, here is what happens.

> Client is 2.2.13pre14. Server is user mode NFS daemon in Red
> Hat 5.1 (plus updates). We have a program which creates a lot
> of files in one NFS-mounted directory, then executes a
> "move-if-changed" script to conditionally rename the files into
> another directory (which may already be populated). Then we
> compile the files. Sometimes the compilation fails with a
> "stale file handle" error on one of the renamed files.

> Looking over the patches and source, I think the problem has to
> do with the elimination of the "update" flag and the
> elimination of the call to "d_drop(old_dentry)" in
> dir.c:nfs_rename(), circa line 1140. In pre14, instead of
> dropping the old dentry, the code calls d_move(old_dentry,
> new_dentry) at the end of the function. Since the NFS file
> handle is part of the dentry, couldn't this result in the old
> file handle being used to access the new file?

Yes. It is in fact a bug in the user mode NFS server that this is not
supported. Nevertheless, the following patch should fix things.

(Note: We should no longer need to check whether (d_count < 2) before
dropping a dentry due to a change in the filehandle, since the stale
inode code is supposed to know about unhashed dentries.)

Cheers,
Trond

--- linux-2.2.13-pre14/fs/nfs/dir.c.orig Fri Oct 1 14:22:08 1999
+++ linux-2.2.13-pre14/fs/nfs/dir.c Fri Oct 1 14:24:10 1999
@@ -462,12 +462,8 @@
goto out_bad;

/* Filehandle matches? */
- if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
- if (!list_empty(&dentry->d_subdirs))
- shrink_dcache_parent(dentry);
- if (dentry->d_count < 2)
- goto out_bad;
- }
+ if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
+ goto out_bad;

/* Ok, remeber that we successfully checked it.. */
nfs_renew_times(dentry);
@@ -476,8 +472,10 @@
out_valid:
return 1;
out_bad:
- if (dentry->d_parent->d_inode)
+ if (dentry->d_parent->d_inode) {
nfs_invalidate_dircache(dentry->d_parent->d_inode);
+ NFS_CACHEINV(dentry->d_parent->d_inode);
+ }
if (inode && S_ISDIR(inode->i_mode))
nfs_invalidate_dircache(inode);
return 0;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/