From owner-svn-src-projects@freebsd.org Mon May 1 21:11:14 2017 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 14CF2D59934 for ; Mon, 1 May 2017 21:11:14 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E3F8B633; Mon, 1 May 2017 21:11:13 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v41LBCN8065916; Mon, 1 May 2017 21:11:12 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v41LBC8F065912; Mon, 1 May 2017 21:11:12 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201705012111.v41LBC8F065912@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Mon, 1 May 2017 21:11:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r317661 - in projects/pnfs-planb-server/sys/fs: nfs nfsserver X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 May 2017 21:11:14 -0000 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); +} +