From owner-svn-src-projects@freebsd.org Mon Sep 2 02:41:28 2019 Return-Path: Delivered-To: svn-src-projects@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 2764ACE56C for ; Mon, 2 Sep 2019 02:41:28 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46MDqX0HbGz48CP; Mon, 2 Sep 2019 02:41:28 +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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E1816B49A; Mon, 2 Sep 2019 02:41:27 +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 x822fRPt072702; Mon, 2 Sep 2019 02:41:27 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x822fRuW072701; Mon, 2 Sep 2019 02:41:27 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201909020241.x822fRuW072701@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Mon, 2 Sep 2019 02:41:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r351682 - projects/nfsv42/sys/fs/nfsserver X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfsv42/sys/fs/nfsserver X-SVN-Commit-Revision: 351682 X-SVN-Commit-Repository: base 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.29 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, 02 Sep 2019 02:41:28 -0000 Author: rmacklem Date: Mon Sep 2 02:41:27 2019 New Revision: 351682 URL: https://svnweb.freebsd.org/changeset/base/351682 Log: Factor the code that creates the mbuf chain from nfsvno_read(). This patch factors the code that creates the mbuf chain and associated iovec from nfsvno_read() into a separate function called nfsrv_createiovec(). This new function is used by nfsvno_getxattr() to avoid code duplication for this. The patch also slightly re-organizes nfsvno_getxattr() so that it first finds out the size of the extended attribute before creating the mbuf chain for VOP_GETEXTATTR(). I need to put the maximum response size for the session in "nd" so that the size of the attribute can be properly limited. Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Mon Sep 2 01:55:55 2019 (r351681) +++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Mon Sep 2 02:41:27 2019 (r351682) @@ -106,6 +106,8 @@ extern int nfsrv_dolocallocks; extern int nfsd_enable_stringtouid; extern struct nfsdevicehead nfsrv_devidhead; +static int nfsrv_createiovec(int, struct mbuf **, struct mbuf **, + struct iovec **); static void nfsrv_pnfscreate(struct vnode *, struct vattr *, struct ucred *, NFSPROC_T *); static void nfsrv_pnfsremovesetup(struct vnode *, NFSPROC_T *, struct vnode **, @@ -781,31 +783,20 @@ out: } /* - * Read vnode op call into mbuf list. + * Create an mbuf chain and an associated iovec that can be used to Read + * or Getextattr of data. + * Upon success, return pointers to the first and last mbufs in the chain + * plus the malloc'd iovec and its iovlen. */ -int -nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred, - struct thread *p, struct mbuf **mpp, struct mbuf **mpendp) +static int +nfsrv_createiovec(int len, struct mbuf **mpp, struct mbuf **mpendp, + struct iovec **ivp) { - struct mbuf *m; - int i; + struct mbuf *m, *m2 = NULL, *m3; struct iovec *iv; - struct iovec *iv2; - int error = 0, len, left, siz, tlen, ioflag = 0; - struct mbuf *m2 = NULL, *m3; - struct uio io, *uiop = &io; - struct nfsheur *nh; + int i, left, siz; - /* - * Attempt to read from a DS file. A return of ENOENT implies - * there is no DS file to read. - */ - error = nfsrv_proxyds(NULL, vp, off, cnt, cred, p, NFSPROC_READDS, mpp, - NULL, mpendp, NULL, NULL, NULL, 0, NULL); - if (error != ENOENT) - return (error); - - len = left = NFSM_RNDUP(cnt); + left = len; m3 = NULL; /* * Generate the mbuf list with the uio_iov ref. to it. @@ -824,9 +815,7 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru m3 = m; m2 = m; } - iv = malloc(i * sizeof (struct iovec), - M_TEMP, M_WAITOK); - uiop->uio_iov = iv2 = iv; + *ivp = iv = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK); m = m3; left = len; i = 0; @@ -844,7 +833,37 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru } m = m->m_next; } - uiop->uio_iovcnt = i; + *mpp = m3; + *mpendp = m2; + return (i); +} + +/* + * Read vnode op call into mbuf list. + */ +int +nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred, + struct thread *p, struct mbuf **mpp, struct mbuf **mpendp) +{ + struct mbuf *m; + struct iovec *iv; + int error = 0, len, tlen, ioflag = 0; + struct mbuf *m3; + struct uio io, *uiop = &io; + struct nfsheur *nh; + + /* + * Attempt to read from a DS file. A return of ENOENT implies + * there is no DS file to read. + */ + error = nfsrv_proxyds(NULL, vp, off, cnt, cred, p, NFSPROC_READDS, mpp, + NULL, mpendp, NULL, NULL, NULL, 0, NULL); + if (error != ENOENT) + return (error); + + len = NFSM_RNDUP(cnt); + uiop->uio_iovcnt = nfsrv_createiovec(len, &m3, &m, &iv); + uiop->uio_iov = iv; uiop->uio_offset = off; uiop->uio_resid = len; uiop->uio_rw = UIO_READ; @@ -855,7 +874,7 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru /* XXX KDM make this more systematic? */ nfsstatsv1.srvbytes[NFSV4OP_READ] += uiop->uio_resid; error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); - free(iv2, M_TEMP); + free(iv, M_TEMP); if (error) { m_freem(m3); *mpp = NULL; @@ -871,7 +890,7 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru } else if (len != tlen || tlen != cnt) nfsrv_adj(m3, len - tlen, tlen - cnt); *mpp = m3; - *mpendp = m2; + *mpendp = m; out: NFSEXITCODE(error); @@ -5874,38 +5893,25 @@ int nfsvno_getxattr(struct vnode *vp, char *name, struct ucred *cred, struct thread *p, struct mbuf **mpp, struct mbuf **mpendp, int *lenp) { - struct iovec *ivp, *ivp2; + struct iovec *iv; struct uio io, *uiop = &io; - struct mbuf *mp, *mp2 = NULL, *mp3 = NULL; - int alen, error, i, len, maxiov, tlen; + struct mbuf *m, *m2; + int alen, error, len, tlen; size_t siz; - maxiov = (NFS_SRVMAXIO + MCLBYTES - 1) / MCLBYTES; - if (maxiov < 1) - maxiov = 1; - ivp2 = ivp = mallocarray(maxiov, sizeof(*ivp), M_TEMP, M_WAITOK); - len = 0; - i = 0; - while (i < maxiov) { - NFSMGET(mp); - MCLGET(mp, M_WAITOK); - mp->m_len = M_SIZE(mp); - if (len == 0) { - mp3 = mp2 = mp; - } else { - mp2->m_next = mp; - mp2 = mp; - } - len += mp->m_len; - ivp->iov_base = mtod(mp, caddr_t); - ivp->iov_len = mp->m_len; - i++; - ivp++; - } - uiop->uio_iov = ivp2; - uiop->uio_iovcnt = i; + /* First, find out the size of the extended attribute. */ + error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, + &siz, cred, p); + if (error != 0) + return (NFSERR_NOXATTR); + if (siz > 1000000) + return (NFSERR_XATTR2BIG); + len = siz; + tlen = NFSM_RNDUP(len); + uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv); + uiop->uio_iov = iv; uiop->uio_offset = 0; - uiop->uio_resid = len; + uiop->uio_resid = tlen; uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = p; @@ -5921,28 +5927,23 @@ nfsvno_getxattr(struct vnode *vp, char *name, struct u if (error != 0) goto out; if (uiop->uio_resid > 0) { - alen = len; - len -= uiop->uio_resid; + alen = tlen; + len = tlen - uiop->uio_resid; tlen = NFSM_RNDUP(len); - nfsrv_adj(mp3, alen - tlen, tlen - len); - } else { - error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, - &siz, cred, p); - if (error == 0 && len < siz) - error = NFSERR_XATTR2BIG; + if (alen != tlen) + printf("nfsvno_getxattr: weird size read\n"); + nfsrv_adj(m, alen - tlen, tlen - len); } - if (error == 0) { - *lenp = len; - *mpp = mp3; - *mpendp = mp; - } + *lenp = len; + *mpp = m; + *mpendp = m2; out: if (error != 0) { - m_freem(mp3); + m_freem(m); *lenp = 0; } - free(ivp2, M_TEMP); + free(iv, M_TEMP); NFSEXITCODE(error); return (error); }