kern/135412: [zfs] [nfs] zfs(v13)+nfs and open(..., O_WRONLY|O_CREAT|O_EXCL, ...)

Jaakko Heinonen jh at saunalahti.fi
Tue Jun 30 16:11:36 UTC 2009


On 2009-06-30, Danny Braniss wrote:
> 	This pr is realy holding me back, I can't upgrade this server, and
> telling serveral tens of users to us cp, etc is not an option. The open
> works fine if not using O_EXCL. 

I guess that r185586 needs to be MFCd to stable/7. Here's an untested
patch against stable/7:

%%%
Index: sys/nfsserver/nfs_serv.c
===================================================================
--- sys/nfsserver/nfs_serv.c	(revision 195189)
+++ sys/nfsserver/nfs_serv.c	(working copy)
@@ -1656,13 +1656,12 @@ nfsrv_create(struct nfsrv_descript *nfsd
 	caddr_t bpos;
 	int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
 	int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
-	caddr_t cp;
 	struct mbuf *mb, *mreq;
 	struct vnode *dirp = NULL;
 	nfsfh_t nfh;
 	fhandle_t *fhp;
 	u_quad_t tempsize;
-	u_char cverf[NFSX_V3CREATEVERF];
+	struct timespec cverf;
 	struct mount *mp = NULL;
 	int tvfslocked;
 	int vfslocked;
@@ -1741,8 +1740,11 @@ nfsrv_create(struct nfsrv_descript *nfsd
 			nfsm_srvsattr(vap);
 			break;
 		case NFSV3CREATE_EXCLUSIVE:
-			cp = nfsm_dissect_nonblock(caddr_t, NFSX_V3CREATEVERF);
-			bcopy(cp, cverf, NFSX_V3CREATEVERF);
+			tl = nfsm_dissect_nonblock(u_int32_t *,
+			    NFSX_V3CREATEVERF);
+			/* Unique bytes, endianness is not important. */
+			cverf.tv_sec  = tl[0];
+			cverf.tv_nsec = tl[1];
 			exclusive_flag = 1;
 			break;
 		};
@@ -1788,8 +1790,7 @@ nfsrv_create(struct nfsrv_descript *nfsd
 				if (exclusive_flag) {
 					exclusive_flag = 0;
 					VATTR_NULL(vap);
-					bcopy(cverf, (caddr_t)&vap->va_atime,
-						NFSX_V3CREATEVERF);
+					vap->va_atime = cverf;
 					error = VOP_SETATTR(nd.ni_vp, vap, cred,
 						td);
 				}
@@ -1873,7 +1874,7 @@ nfsrv_create(struct nfsrv_descript *nfsd
 	}
 	if (v3) {
 		if (exclusive_flag && !error &&
-			bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
+		    bcmp(&cverf, &vap->va_atime, sizeof (cverf)))
 			error = EEXIST;
 		if (dirp == nd.ni_dvp)
 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
%%%

Please report back if you try the patch.

-- 
Jaakko


More information about the freebsd-stable mailing list