[lkml]   [2005]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    SubjectNFS: NFS3 lookup fails if creating a file with O_EXCL & multiple mountpoints in pathname
    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

    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.


    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-> & O_EXCL) != 0;

    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to
    More majordomo info at
    Please read the FAQ at

     \ /
      Last update: 2005-06-07 04:38    [W:0.027 / U:160.688 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site