Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Jul 2017 19:18:37 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r321029 - in stable/11/sys/fs: nfs nfsclient
Message-ID:  <201707151918.v6FJIb9p014487@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Jul 15 19:18:37 2017
New Revision: 321029
URL: https://svnweb.freebsd.org/changeset/base/321029

Log:
  MFC: r320345
  Add support to the NFSv4.1/pNFS client for commits through the DS.
  
  A NFSv4.1/pNFS server using File Layout can specify that Commit operations
  are to be done against the DS instead of MDS. Since no extant pNFS
  server did this, the code was untested and "#ifdef notyet".
  The FreeBSD pNFS server I am developing does specify that Commits be done
  through the DS, so the code has been enabled/tested.
  This patch should only affect the case of a pNFS server that specfies
  Commits through the DS.
  
  Relnotes:	yes

Modified:
  stable/11/sys/fs/nfs/nfs_var.h
  stable/11/sys/fs/nfsclient/nfs_clnode.c
  stable/11/sys/fs/nfsclient/nfs_clrpcops.c
  stable/11/sys/fs/nfsclient/nfs_clvnops.c
  stable/11/sys/fs/nfsclient/nfsnode.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/fs/nfs/nfs_var.h
==============================================================================
--- stable/11/sys/fs/nfs/nfs_var.h	Sat Jul 15 18:44:03 2017	(r321028)
+++ stable/11/sys/fs/nfs/nfs_var.h	Sat Jul 15 19:18:37 2017	(r321029)
@@ -490,7 +490,7 @@ int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, 
     int, uint64_t, uint64_t, nfsv4stateid_t *, int, uint32_t *, struct ucred *,
     NFSPROC_T *, void *);
 int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *);
-int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t,
+int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, int,
     struct ucred *, NFSPROC_T *);
 int nfscl_findlayoutforio(struct nfscllayout *, uint64_t, uint32_t,
     struct nfsclflayout **);

Modified: stable/11/sys/fs/nfsclient/nfs_clnode.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clnode.c	Sat Jul 15 18:44:03 2017	(r321028)
+++ stable/11/sys/fs/nfsclient/nfs_clnode.c	Sat Jul 15 19:18:37 2017	(r321029)
@@ -259,10 +259,12 @@ ncl_inactive(struct vop_inactive_args *ap)
 
 	/*
 	 * NMODIFIED means that there might be dirty/stale buffers
-	 * associated with the NFS vnode.  None of the other flags are
-	 * meaningful after the vnode is unused.
+	 * associated with the NFS vnode.
+	 * NDSCOMMIT means that the file is on a pNFS server and commits
+	 * should be done to the DS.
+	 * None of the other flags are meaningful after the vnode is unused.
 	 */
-	np->n_flag &= NMODIFIED;
+	np->n_flag &= (NMODIFIED | NDSCOMMIT);
 	mtx_unlock(&np->n_mtx);
 	return (0);
 }

Modified: stable/11/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clrpcops.c	Sat Jul 15 18:44:03 2017	(r321028)
+++ stable/11/sys/fs/nfsclient/nfs_clrpcops.c	Sat Jul 15 19:18:37 2017	(r321029)
@@ -114,7 +114,8 @@ static int nfsrpc_fillsa(struct nfsmount *, struct soc
 static void nfscl_initsessionslots(struct nfsclsession *);
 static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
-    struct nfsclflayout *, uint64_t, uint64_t, struct ucred *, NFSPROC_T *);
+    struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *,
+    NFSPROC_T *);
 static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
     struct nfsclds *, uint64_t, int, struct nfsfh *, struct ucred *,
     NFSPROC_T *);
@@ -123,10 +124,8 @@ static int nfsrpc_writeds(vnode_t, struct uio *, int *
     struct nfsfh *, int, struct ucred *, NFSPROC_T *);
 static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
     struct nfsclds *, struct nfsclds **);
-#ifdef notyet
 static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
-    struct nfsfh *, struct ucred *, NFSPROC_T *, void *);
-#endif
+    struct nfsfh *, struct ucred *, NFSPROC_T *);
 static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
     uint64_t, uint64_t, nfsv4stateid_t *, int, int);
 static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *,
@@ -5429,7 +5428,7 @@ nfscl_initsessionslots(struct nfsclsession *sep)
  */
 int
 nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
-    uint32_t rwaccess, struct ucred *cred, NFSPROC_T *p)
+    uint32_t rwaccess, int docommit, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsnode *np = VTONFS(vp);
 	struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
@@ -5513,7 +5512,8 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
 			if (dip != NULL) {
 				error = nfscl_doflayoutio(vp, uiop, iomode,
 				    must_commit, &eof, &stateid, rwaccess, dip,
-				    layp, rflp, off, xfer, newcred, p);
+				    layp, rflp, off, xfer, docommit, newcred,
+				    p);
 				nfscl_reldevinfo(dip);
 				lastbyte = off + xfer - 1;
 				if (error == 0) {
@@ -5589,10 +5589,10 @@ static int
 nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo *dp,
     struct nfscllayout *lyp, struct nfsclflayout *flp, uint64_t off,
-    uint64_t len, struct ucred *cred, NFSPROC_T *p)
+    uint64_t len, int docommit, struct ucred *cred, NFSPROC_T *p)
 {
 	uint64_t io_off, rel_off, stripe_unit_size, transfer, xfer;
-	int commit_thru_mds, error = 0, stripe_index, stripe_pos;
+	int commit_thru_mds, error, stripe_index, stripe_pos;
 	struct nfsnode *np;
 	struct nfsfh *fhp;
 	struct nfsclds **dspp;
@@ -5603,12 +5603,13 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i
 	stripe_pos = (rel_off / stripe_unit_size + flp->nfsfl_stripe1) %
 	    dp->nfsdi_stripecnt;
 	transfer = stripe_unit_size - (rel_off % stripe_unit_size);
+	error = 0;
 
 	/* Loop around, doing I/O for each stripe unit. */
 	while (len > 0 && error == 0) {
 		stripe_index = nfsfldi_stripeindex(dp, stripe_pos);
 		dspp = nfsfldi_addr(dp, stripe_index);
-		if (len > transfer)
+		if (len > transfer && docommit == 0)
 			xfer = transfer;
 		else
 			xfer = len;
@@ -5632,11 +5633,33 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *i
 				fhp = np->n_fhp;
 			io_off = off;
 		}
-		if ((flp->nfsfl_util & NFSFLAYUTIL_COMMIT_THRU_MDS) != 0)
+		if ((flp->nfsfl_util & NFSFLAYUTIL_COMMIT_THRU_MDS) != 0) {
 			commit_thru_mds = 1;
-		else
+			if (docommit != 0)
+				error = EIO;
+		} else {
 			commit_thru_mds = 0;
-		if (rwflag == FREAD)
+			mtx_lock(&np->n_mtx);
+			np->n_flag |= NDSCOMMIT;
+			mtx_unlock(&np->n_mtx);
+		}
+		if (docommit != 0) {
+			if (error == 0)
+				error = nfsrpc_commitds(vp, io_off, xfer,
+				    *dspp, fhp, cred, p);
+			if (error == 0) {
+				/*
+				 * Set both eof and uio_resid = 0 to end any
+				 * loops.
+				 */
+				*eofp = 1;
+				uiop->uio_resid = 0;
+			} else {
+				mtx_lock(&np->n_mtx);
+				np->n_flag &= ~NDSCOMMIT;
+				mtx_unlock(&np->n_mtx);
+			}
+		} else if (rwflag == FREAD)
 			error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
 			    io_off, xfer, fhp, cred, p);
 		else {
@@ -5872,13 +5895,12 @@ nfscl_getsameserver(struct nfsmount *nmp, struct nfscl
 	return (NFSDSP_NOTFOUND);
 }
 
-#ifdef notyet
 /*
- * NFS commit rpc to a DS.
+ * NFS commit rpc to a NFSv4.1 DS.
  */
 static int
 nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
-    struct nfsfh *fhp, struct ucred *cred, NFSPROC_T *p, void *stuff)
+    struct nfsfh *fhp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
@@ -5886,6 +5908,7 @@ nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, 
 	struct nfssockreq *nrp;
 	int error;
 	
+	nd->nd_mrep = NULL;
 	nfscl_reqstart(nd, NFSPROC_COMMITDS, nmp, fhp->nfh_fh, fhp->nfh_len,
 	    NULL, &dsp->nfsclds_sess);
 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
@@ -5898,7 +5921,7 @@ nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, 
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
-	if (error)
+	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
@@ -5915,7 +5938,6 @@ nfsmout:
 	mbuf_freem(nd->nd_mrep);
 	return (error);
 }
-#endif
 
 /*
  * Set up the XDR arguments for the LayoutGet operation.

Modified: stable/11/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clvnops.c	Sat Jul 15 18:44:03 2017	(r321028)
+++ stable/11/sys/fs/nfsclient/nfs_clvnops.c	Sat Jul 15 19:18:37 2017	(r321029)
@@ -1369,7 +1369,7 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct
 	attrflag = 0;
 	if (NFSHASPNFS(nmp))
 		error = nfscl_doiods(vp, uiop, NULL, NULL,
-		    NFSV4OPEN_ACCESSREAD, cred, uiop->uio_td);
+		    NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
 	NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
 	if (error != 0)
 		error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
@@ -1400,7 +1400,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struc
 	attrflag = 0;
 	if (NFSHASPNFS(nmp))
 		error = nfscl_doiods(vp, uiop, iomode, must_commit,
-		    NFSV4OPEN_ACCESSWRITE, cred, uiop->uio_td);
+		    NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
 	NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
 	if (error != 0)
 		error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
@@ -2557,16 +2557,34 @@ ncl_commit(struct vnode *vp, u_quad_t offset, int cnt,
 {
 	struct nfsvattr nfsva;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+	struct nfsnode *np;
+	struct uio uio;
 	int error, attrflag;
 
-	mtx_lock(&nmp->nm_mtx);
-	if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
+	np = VTONFS(vp);
+	error = EIO;
+	attrflag = 0;
+	if (NFSHASPNFS(nmp) && (np->n_flag & NDSCOMMIT) != 0) {
+		uio.uio_offset = offset;
+		uio.uio_resid = cnt;
+		error = nfscl_doiods(vp, &uio, NULL, NULL,
+		    NFSV4OPEN_ACCESSWRITE, 1, cred, td);
+		if (error != 0) {
+			mtx_lock(&np->n_mtx);
+			np->n_flag &= ~NDSCOMMIT;
+			mtx_unlock(&np->n_mtx);
+		}
+	}
+	if (error != 0) {
+		mtx_lock(&nmp->nm_mtx);
+		if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
+			mtx_unlock(&nmp->nm_mtx);
+			return (0);
+		}
 		mtx_unlock(&nmp->nm_mtx);
-		return (0);
+		error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
+		    &attrflag, NULL);
 	}
-	mtx_unlock(&nmp->nm_mtx);
-	error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
-	    &attrflag, NULL);
 	if (attrflag != 0)
 		(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL,
 		    0, 1);

Modified: stable/11/sys/fs/nfsclient/nfsnode.h
==============================================================================
--- stable/11/sys/fs/nfsclient/nfsnode.h	Sat Jul 15 18:44:03 2017	(r321028)
+++ stable/11/sys/fs/nfsclient/nfsnode.h	Sat Jul 15 19:18:37 2017	(r321029)
@@ -158,6 +158,7 @@ struct nfsnode {
 #define	NNOLAYOUT	0x00020000  /* Can't get a layout for this file */
 #define	NWRITEOPENED	0x00040000  /* Has been opened for writing */
 #define	NHASBEENLOCKED	0x00080000  /* Has been file locked. */
+#define	NDSCOMMIT	0x00100000  /* Commit is done via the DS. */
 
 /*
  * Convert between nfsnode pointers and vnode pointers



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