Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1668

kernel-2.6.18-128.1.10.el5.src.rpm

From: Jeff Layton <jlayton@redhat.com>
Date: Wed, 26 Sep 2007 09:24:10 -0400
Subject: [nfs] Set attrmask on NFS4_CREATE_EXCLUSIVE reply
Message-id: 200709261324.l8QDOAZg031559@barsoom.rdu.redhat.com
O-Subject: [RHEL5.2 PATCH 1/2] BZ#242482: Set attrmask correctly on NFS4_CREATE_EXCLUSIVE reply
Bugzilla: 242482

When an exclusive create is done on NFSv4, the file often ends up with a
nonsensical mtime. This is because servers often save the verifier in
the mtime field, and the client doesn't overwrite it. To fix this takes
a client and server side patch. Server-side first...

RFC 3530 says:

   If the server uses an attribute to store the exclusive create
   verifier, it will signify which attribute by setting the appropriate
   bit in the attribute mask that is returned in the results.

knfsd uses the atime and mtime to store the verifier, but sends a zeroed
out bitmask back to the client. This patch makes sure that we set the
correct bits in the bitmask in this situation.

This patch went upstream in early June and was verified by inspecting
packet traces and by testing the simple reproducer on a client with
patch #2.

Acked-by: Peter Staubach <staubach@redhat.com>
Acked-by: Steve Dickson <SteveD@redhat.com>

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6bae607..cd85672 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -105,9 +105,16 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
 		status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
 					open->op_fname.len, &open->op_iattr,
 					&resfh, open->op_createmode,
-					(u32 *)open->op_verf.data, &open->op_truncate);
-	}
-	else {
+					(u32 *)open->op_verf.data,
+					&open->op_truncate);
+
+		/* If we ever decide to use different attrs to store the
+		 * verifier in nfsd_create_v3, then we'll need to change this
+		 */
+		if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
+			open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
+						FATTR4_WORD1_TIME_MODIFY);
+	} else {
 		status = nfsd_lookup(rqstp, current_fh,
 				     open->op_fname.data, open->op_fname.len, &resfh);
 		fh_unlock(current_fh);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index e069816..78388e1 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1255,7 +1255,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
 		/* solaris7 gets confused (bugid 4218508) if these have
-		 * the high bit set, so just clear the high bits.
+		 * the high bit set, so just clear the high bits. If this is
+		 * ever changed to use different attrs for storing the
+		 * verifier, then do_open_lookup() will also need to be fixed
+		 * accordingly.
 		 */
 		v_mtime = verifier[0]&0x7fffffff;
 		v_atime = verifier[1]&0x7fffffff;