NFS: NFS3 lookup fails if creating a file with O_EXCL & multiplemountpoints in pathname

From: Linda Dunaphant
Date: Mon Jun 06 2005 - 21:35:44 EST


Hi Trond,

One of our applications was doing an open on a NFS client with the flags
set for O_WRONLY|O_CREAT|O_EXCL|0x4. There are numerous symlinks in the
pathname for the file that go into two different NFS filesystems. The
file create works properly if the filesystems are mounted as NFS2, but
it fails with NFS3 mounts.

In nfs_lookup() there is a check to see if it is an exclusive create.
If it is exclusive, nfs_lookup() bypasses ("optimizes" away) the rest
of the lookup. When the problem occurs, I see it stop the lookup too
early. This only occurs when the basename portion of the pathname is
not currently in the NFS cache from a previous non- O_EXCL pathname lookup.

The nfs_is_exclusive_create() was returning TRUE, even when the
search wasn't at the last pathname component. This occurred because
the LOOKUP_CONTINUE flag is reset when it crosses the second
mountpoint into the NFS filesystem. nfs_is_exclusive_create() was
trying to use this flag to determine if it was at the end point
of the pathname search. Since it was reset when it crossed the
mountpoint boundary, it returned TRUE several pathname levels too
early.

I changed the nfs_is_exclusive_create() to use the LOOKUP_PARENT
flag instead of the LOOKUP_CONTINUE flag. I found that LOOKUP_PARENT
stays set until you get to the very last pathname level, which is
the correct point for it to check whether it is an exclusive create.

The following patch for 2.6.12-rc5 fixed the problem.

Regards,
Linda

diff -ura base/fs/nfs/dir.c new/fs/nfs/dir.c
--- base/fs/nfs/dir.c 2005-06-06 20:59:22.000000000 -0400
+++ new/fs/nfs/dir.c 2005-06-06 22:14:24.000000000 -0400
@@ -705,7 +705,7 @@
{
if (NFS_PROTO(dir)->version == 2)
return 0;
- if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+ if (!nd || (nd->flags & LOOKUP_PARENT) || !(nd->flags & LOOKUP_CREATE))
return 0;
return (nd->intent.open.flags & O_EXCL) != 0;
}


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