Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Jan 2001 23:54:30 -0800 (PST)
From:      Matt Dillon <dillon@earth.backplane.com>
To:        Marc Culler <culler@math.uic.edu>, freebsd-stable@FreeBSD.ORG
Subject:   NFSv3 O_EXCL file create - protocol spec & solution (was Re: Bug in NFSv3 client)
Message-ID:  <200101040754.f047sUW55674@earth.backplane.com>
References:  <20010103155533.B71238@math.uic.edu> <200101032243.f03Mhar51440@earth.backplane.com> <200101032308.f03N84f51776@earth.backplane.com> <200101032322.f03NMTK51973@earth.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help
    The RFC (1813) says that the exclusive-file-create NFS op passes a 
    verifier.  It says, and I quote:

      "One aspect of the NFS version 3 protocol CREATE procedure
      warrants particularly careful consideration: the mechanism
      introduced to support the reliable exclusive creation of
      regular files. The mechanism comes into play when how.mode
      is EXCLUSIVE.  In this case, how.verf contains a verifier
      that can reasonably be expected to be unique.  A
      combination of a client identifier, perhaps the client
      network address, and a unique number generated by the
      client, perhaps the RPC transaction identifier, may be
      appropriate."

    What that means is that the verifier can be anything.
    Here's why the FreeBSD server was storing the verifier as the 
    file access time:

      "verifier must be stored in stable storage to prevent
      erroneous failure on retransmission of the request. It is
      assumed that an exclusive create is being performed
      because exclusive semantics are critical to the
      application. Because of the expected usage, exclusive
      CREATE does not rely solely on the normally volatile
      duplicate request cache for storage of the verifier. The
      duplicate request cache in volatile storage does not
      survive a crash and may actually flush on a long network
      partition, opening failure windows.  In the UNIX local
      file system environment, the expected storage location for
      the verifier on creation is the metadata (time stamps) of
      the file. For this reason, an exclusive file create may
      not include initial attributes because the server would
      have nowhere to store the verifier."

    Ahhh, so now we know why FreeBSD is passing the IP address of
    the interface plus a 'unique' number!  Or trying anyway.

    And also:

      "Once the client has performed a successful exclusive
      create, it must issue a SETATTR to set the correct file
      attributes.  Until it does so, it should not rely upon any
      of the file attributes, since the server implementation
      may need to overload file metadata to store the verifier."


    What this means is that the FreeBSD client is supposed to call
    SETATTR to set the correct file attributes after the O_EXCL open
    succeeds.  It is in fact doing this, but the 'atime' attribute
    in the 'vap' structure is not initialized, so the SETATTR call
    never actually fixes up the access time.

    Solaris probably shouldn't be generating an error for the 'bogus'
    time specification, as that can race with an O_EXCL create, but
    I think fixing the FreeBSD clients to do the proper SETATTR
    should solve the problem.

    I've included the patch below.  The patch will fix FreeBSD
    clients.  I will commit it to -current now and to -stable in
    two days if there aren't any problems.  (Throw away any previous
    patches you might have applied).

						-Matt

Index: nfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.150
diff -u -r1.150 nfs_vnops.c
--- nfs_vnops.c	2000/01/05 00:32:18	1.150
+++ nfs_vnops.c	2001/01/04 07:48:37
@@ -1436,8 +1436,21 @@
 		}
 		if (newvp)
 			vput(newvp);
-	} else if (v3 && (fmode & O_EXCL))
+	} else if (v3 && (fmode & O_EXCL)) {
+		/*
+		 * We are normally called with only a partially initialized
+		 * VAP.  Since the NFSv3 spec says that server may use the
+		 * file attributes to store the verifier, the spec requires
+		 * us to do a SETATTR RPC. FreeBSD servers store the verifier
+		 * in atime, but we can't really assume that all servers will
+		 * so we ensure that our SETATTR sets both atime and mtime.
+		 */
+		if (vap->va_mtime.tv_sec == VNOVAL)
+			vfs_timestamp(&vap->va_mtime);
+		if (vap->va_atime.tv_sec == VNOVAL)
+			vap->va_atime = vap->va_mtime;
 		error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
+	}
 	if (!error) {
 		if (cnp->cn_flags & MAKEENTRY)
 			cache_enter(dvp, newvp, cnp);


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101040754.f047sUW55674>