Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 May 2017 21:11:12 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r317661 - in projects/pnfs-planb-server/sys/fs: nfs nfsserver
Message-ID:  <201705012111.v41LBC8F065912@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Mon May  1 21:11:12 2017
New Revision: 317661
URL: https://svnweb.freebsd.org/changeset/base/317661

Log:
  Add checks for a Layout plus Open/Write_access or Write_delegation to the
  nfsrv_proxyds() function for the Getattr case. Do the attribute updates for
  Close and DelegReturn for the write cases.
  This should make it perform better for clients such as Linux, where the
  value of vfs.nfsd.pnfsgetdsattr needs to be set non-zero to keep the file's
  attributes (mainly size) up to date.

Modified:
  projects/pnfs-planb-server/sys/fs/nfs/nfs_var.h
  projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdport.c
  projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c
  projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdstate.c

Modified: projects/pnfs-planb-server/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfs/nfs_var.h	Mon May  1 20:04:07 2017	(r317660)
+++ projects/pnfs-planb-server/sys/fs/nfs/nfs_var.h	Mon May  1 21:11:12 2017	(r317661)
@@ -109,9 +109,9 @@ int nfsrv_openctrl(struct nfsrv_descript
 int nfsrv_opencheck(nfsquad_t, nfsv4stateid_t *, struct nfsstate *,
     vnode_t, struct nfsrv_descript *, NFSPROC_T *, int);
 int nfsrv_openupdate(vnode_t, struct nfsstate *, nfsquad_t,
-    nfsv4stateid_t *, struct nfsrv_descript *, NFSPROC_T *);
+    nfsv4stateid_t *, struct nfsrv_descript *, NFSPROC_T *, int *);
 int nfsrv_delegupdate(struct nfsrv_descript *, nfsquad_t, nfsv4stateid_t *,
-    vnode_t, int, struct ucred *, NFSPROC_T *);
+    vnode_t, int, struct ucred *, NFSPROC_T *, int *);
 int nfsrv_releaselckown(struct nfsstate *, nfsquad_t, NFSPROC_T *);
 void nfsrv_zapclient(struct nfsclient *, NFSPROC_T *);
 int nfssvc_idname(struct nfsd_idargs *);
@@ -149,8 +149,7 @@ int nfsrv_layoutreturn(struct nfsrv_desc
 int nfsrv_getdevinfo(char *, int, uint32_t *, uint32_t *, int *, char **);
 void nfsrv_freealllayoutsanddevids(void);
 void nfsrv_createdevids(struct nfsd_nfsd_args *, NFSPROC_T *);
-int nfsrv_findlayout(struct nfsrv_descript *, fhandle_t *, NFSPROC_T *,
-    struct nfslayout **);
+int nfsrv_checkdsattr(struct nfsrv_descript *, vnode_t, NFSPROC_T *);
 
 /* nfs_nfsdserv.c */
 int nfsrvd_access(struct nfsrv_descript *, int,

Modified: projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdport.c	Mon May  1 20:04:07 2017	(r317660)
+++ projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdport.c	Mon May  1 21:11:12 2017	(r317661)
@@ -257,8 +257,8 @@ nfsvno_getattr(struct vnode *vp, struct 
 
 	/*
 	 * Acquire the Change, Size and Modify Time attributes from the DS file
-	 * for a pNFS server.  A return of ENOENT indicates that there is
-	 * no DS file or the MetaData file has up to date attributes.
+	 * for a pNFS server.  A return of 0 indicates that there are
+	 * DS file attributes to be merged into the returned attributes.
 	 */
 	gotattr = 0;
 	error = nfsrv_proxyds(nd, vp, 0, 0, nd->nd_cred, p, NFSPROC_GETATTR,
@@ -3831,13 +3831,11 @@ nfsrv_proxyds(struct nfsrv_descript *nd,
     char *cp, struct mbuf **mpp2, struct nfsvattr *nap, struct acl *aclp)
 {
 	struct nfsmount *nmp;
-	struct nfslayouthash *lhyp;
-	struct nfslayout *lyp;
 	fhandle_t fh;
 	struct vnode *dvp;
 	struct pnfsdsattr dsattr;
 	char *buf;
-	int buflen, error, ret;
+	int buflen, error;
 
 	NFSD_DEBUG(4, "in nfsrv_proxyds\n");
 	/*
@@ -3873,32 +3871,16 @@ nfsrv_proxyds(struct nfsrv_descript *nd,
 			nap->na_mtime = dsattr.dsa_mtime;
 		}
 
-		/* If nfsrv_pnfsgetdsattr isn't set, just return ENXIO. */
-		if (nfsrv_pnfsgetdsattr == 0) {
-			free(buf, M_TEMP);
-			return (error);
-		}
-
 		/*
-		 * For Getattr, check to see if there is a write layout
-		 * issued to a client.  If there is no write layout, return
-		 * ENXIO to indicate that the MetaData file's attributes
-		 * are current w.r.t. the file, except the va_filerev, which
-		 * has already been acquired from the extended attribute.
+		 * If nfsrv_pnfsgetdsattr is 0 or nfsrv_checkdsattr() returns
+		 * 0, just return now.  nfsrv_checkdsattr() returns 0 if there
+		 * is no Read/Write layout + either an Open/Write_access or
+		 * Write delegation issued to a client for the file.
 		 */
-		ret = nfsvno_getfh(vp, &fh, p);
-		if (ret == 0) {
-			lhyp = NFSLAYOUTHASH(&fh);
-			NFSLOCKLAYOUT(lhyp);
-			ret = nfsrv_findlayout(nd, &fh, p, &lyp);
-			if (ret != 0 || lyp->lay_rw == 0) {
-				NFSUNLOCKLAYOUT(lhyp);
-				free(buf, M_TEMP);
-				NFSD_DEBUG(4, "nfsrv_proxyds: getattr "
-				    "nolayout=%d\n", ret);
-				return (error);
-			}
-			NFSUNLOCKLAYOUT(lhyp);
+		if (nfsrv_pnfsgetdsattr == 0 || nfsrv_checkdsattr(nd, vp, p) ==
+		    0) {
+			free(buf, M_TEMP);
+			return (error);
 		}
 	}
 

Modified: projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c	Mon May  1 20:04:07 2017	(r317660)
+++ projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c	Mon May  1 21:11:12 2017	(r317661)
@@ -3139,7 +3139,7 @@ nfsrvd_close(struct nfsrv_descript *nd, 
 {
 	u_int32_t *tl;
 	struct nfsstate st, *stp = &st;
-	int error = 0;
+	int error = 0, writeacc;
 	nfsv4stateid_t stateid;
 	nfsquad_t clientid;
 	struct nfsvattr na;
@@ -3182,9 +3182,11 @@ nfsrvd_close(struct nfsrv_descript *nd, 
 		nd->nd_flag |= ND_IMPLIEDCLID;
 		nd->nd_clientid.qval = clientid.qval;
 	}
-	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p);
+	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
+	    &writeacc);
 	/* For pNFS, update the attributes. */
-	nfsrv_updatemdsattr(vp, &na, p);
+	if (writeacc != 0)
+		nfsrv_updatemdsattr(vp, &na, p);
 	vput(vp);
 	if (!nd->nd_repstat) {
 		/*
@@ -3238,7 +3240,7 @@ nfsrvd_delegpurge(struct nfsrv_descript 
 		nd->nd_clientid.qval = clientid.qval;
 	}
 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL,
-	    NFSV4OP_DELEGPURGE, nd->nd_cred, p);
+	    NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL);
 nfsmout:
 	NFSEXITCODE2(error, nd);
 	return (error);
@@ -3252,9 +3254,10 @@ nfsrvd_delegreturn(struct nfsrv_descript
     vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
 {
 	u_int32_t *tl;
-	int error = 0;
+	int error = 0, writeacc;
 	nfsv4stateid_t stateid;
 	nfsquad_t clientid;
+	struct nfsvattr na;
 
 	NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 	stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
@@ -3273,7 +3276,10 @@ nfsrvd_delegreturn(struct nfsrv_descript
 		nd->nd_clientid.qval = clientid.qval;
 	}
 	nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp,
-	    NFSV4OP_DELEGRETURN, nd->nd_cred, p);
+	    NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc);
+	/* For pNFS, update the attributes. */
+	if (writeacc != 0)
+		nfsrv_updatemdsattr(vp, &na, p);
 nfsmout:
 	vput(vp);
 	NFSEXITCODE2(error, nd);
@@ -3337,7 +3343,8 @@ nfsrvd_openconfirm(struct nfsrv_descript
 		nd->nd_flag |= ND_IMPLIEDCLID;
 		nd->nd_clientid.qval = clientid.qval;
 	}
-	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p);
+	nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
+	    NULL);
 	if (!nd->nd_repstat) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 		*tl++ = txdr_unsigned(stateid.seqid);
@@ -3440,7 +3447,7 @@ nfsrvd_opendowngrade(struct nfsrv_descri
 	}
 	if (!nd->nd_repstat)
 		nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid,
-		    nd, p);
+		    nd, p, NULL);
 	if (!nd->nd_repstat) {
 		/* For NFSv4.1, set the Current StateID. */
 		if ((nd->nd_flag & ND_NFSV41) != 0) {

Modified: projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdstate.c	Mon May  1 20:04:07 2017	(r317660)
+++ projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdstate.c	Mon May  1 21:11:12 2017	(r317661)
@@ -186,6 +186,8 @@ static int nfsrv_setdsserver(char *dspat
     struct nfsdevice **dsp);
 static void nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost);
 static void nfsrv_freealldevids(void);
+static int nfsrv_findlayout(struct nfsrv_descript *nd, fhandle_t *fhp,
+    NFSPROC_T *, struct nfslayout **lypp);
 
 /*
  * Scan the client list for a match and either return the current one,
@@ -3283,7 +3285,8 @@ out:
  */
 APPLESTATIC int
 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
-    nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p)
+    nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p,
+    int *retwriteaccessp)
 {
 	struct nfsstate *stp, *ownerstp;
 	struct nfsclient *clp;
@@ -3386,6 +3389,12 @@ nfsrv_openupdate(vnode_t vp, struct nfss
 	} else if (new_stp->ls_flags & NFSLCK_CLOSE) {
 		ownerstp = stp->ls_openowner;
 		lfp = stp->ls_lfp;
+		if (retwriteaccessp != NULL) {
+			if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0)
+				*retwriteaccessp = 1;
+			else
+				*retwriteaccessp = 0;
+		}
 		if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
 			/* Get the lf lock */
 			nfsrv_locklf(lfp);
@@ -3442,7 +3451,7 @@ out:
 APPLESTATIC int
 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
     nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
-    NFSPROC_T *p)
+    NFSPROC_T *p, int *retwriteaccessp)
 {
 	struct nfsstate *stp;
 	struct nfsclient *clp;
@@ -3507,6 +3516,12 @@ nfsrv_delegupdate(struct nfsrv_descript 
 			error = NFSERR_BADSTATEID;
 			goto out;
 		}
+		if (retwriteaccessp != NULL) {
+			if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0)
+				*retwriteaccessp = 1;
+			else
+				*retwriteaccessp = 0;
+		}
 		nfsrv_freedeleg(stp);
 	} else {
 		nfsrv_freedeleglist(&clp->lc_olddeleg);
@@ -6380,7 +6395,7 @@ nfsrv_layoutreturn(struct nfsrv_descript
 /*
  * Look for an existing layout.
  */
-int
+static int
 nfsrv_findlayout(struct nfsrv_descript *nd, fhandle_t *fhp, NFSPROC_T *p,
     struct nfslayout **lypp)
 {
@@ -6792,3 +6807,80 @@ nfsrv_freealldevids(void)
 		nfsrv_freedevid(ds);
 }
 
+/*
+ * Check to see if there is a Read/Write Layout plus either:
+ * - A Write Delegation
+ * or
+ * - An Open with Write_access.
+ * Return 1 if this is the case and 0 otherwise.
+ * This function is used by nfsrv_proxyds() to decide if doing a Proxy
+ * Getattr RPC to the Data Server (DS) is necessary.
+ */
+APPLESTATIC int
+nfsrv_checkdsattr(struct nfsrv_descript *nd, vnode_t vp, NFSPROC_T *p)
+{
+	fhandle_t fh, *tfhp;
+	struct nfsstate *stp;
+	struct nfslayout *lyp;
+	struct nfslayouthash *lhyp;
+	struct nfslockhashhead *hp;
+	struct nfslockfile *lfp;
+	int ret;
+
+	KASSERT((nd->nd_flag & ND_IMPLIEDCLID) != 0,
+	    ("nfsrv_chechdsattr: no nd_clientid\n"));
+	ret = nfsvno_getfh(vp, &fh, p);
+	if (ret != 0)
+		return (0);
+
+	/* First check for a Read/Write Layout. */
+	lhyp = NFSLAYOUTHASH(&fh);
+	NFSLOCKLAYOUT(lhyp);
+	ret = nfsrv_findlayout(nd, &fh, p, &lyp);
+	if (ret != 0 || lyp->lay_rw == 0) {
+		/* None found, so return 0. */
+		NFSUNLOCKLAYOUT(lhyp);
+		return (0);
+	}
+	NFSUNLOCKLAYOUT(lhyp);
+
+	/* Get the nfslockfile for this fh. */
+	NFSLOCKSTATE();
+	hp = NFSLOCKHASH(&fh);
+	LIST_FOREACH(lfp, hp, lf_hash) {
+		tfhp = &lfp->lf_fh;
+		if (NFSVNO_CMPFH(&fh, tfhp))
+			break;
+	}
+	if (lfp == NULL) {
+		/* None found, so return 0. */
+		NFSUNLOCKSTATE();
+		return (0);
+	}
+
+	/* Now, look for a Write delegation for this clientid. */
+	LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
+		if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0 &&
+		    stp->ls_clp->lc_clientid.qval == nd->nd_clientid.qval)
+			break;
+	}
+	if (stp != NULL) {
+		/* Found one, so return 1. */
+		NFSUNLOCKSTATE();
+		return (1);
+	}
+
+	/* No Write delegation, so look for an Open with Write_access. */
+	LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
+		KASSERT((stp->ls_flags & NFSLCK_OPEN) != 0,
+		    ("nfsrv_checkdsattr: Non-open in Open list\n"));
+		if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0 &&
+		    stp->ls_clp->lc_clientid.qval == nd->nd_clientid.qval)
+			break;
+	}
+	NFSUNLOCKSTATE();
+	if (stp != NULL)
+		return (1);
+	return (0);
+}
+



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