svn commit: r363470 - in projects/nfs-over-tls/sys/fs: nfs nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Fri Jul 24 02:19:01 UTC 2020
Author: rmacklem
Date: Fri Jul 24 02:19:00 2020
New Revision: 363470
URL: https://svnweb.freebsd.org/changeset/base/363470
Log:
Update nfsm_uiombuflist() and nfscl_dofflayoutio() so that ext_pgs mbufs
can be used.
The use of ext_pgs mbufs is not yet enabled, since it requires changes
to ktls_encrypt() so that the encrypted pages are not in the same mbuf list.
Modified:
projects/nfs-over-tls/sys/fs/nfs/nfs_var.h
projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c
projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c
Modified: projects/nfs-over-tls/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfs/nfs_var.h Fri Jul 24 01:25:57 2020 (r363469)
+++ projects/nfs-over-tls/sys/fs/nfs/nfs_var.h Fri Jul 24 02:19:00 2020 (r363470)
@@ -363,7 +363,7 @@ void nfsm_set(struct nfsrv_descript *, u_int);
/* nfs_clcomsubs.c */
void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
-struct mbuf *nfsm_uiombuflist(struct uio *, int, struct mbuf **, char **);
+struct mbuf *nfsm_uiombuflist(struct uio *, int, u_int);
nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
Modified: projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 01:25:57 2020 (r363469)
+++ projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 02:19:00 2020 (r363470)
@@ -160,26 +160,35 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *ui
* NOTE: can ony handle iovcnt == 1
*/
struct mbuf *
-nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
+nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
{
char *uiocp;
struct mbuf *mp, *mp2, *firstmp;
- int xfer, left, mlen;
+ int extpg, extpgsiz = 0, i, left, mlen, rem, xfer;
int uiosiz, clflg;
- char *tcp;
+ char *mcp, *tcp;
KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
- if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- if (clflg != 0)
- NFSMCLGET(mp, M_WAITOK);
- else
- NFSMGET(mp);
+ if (maxext > 0) {
+ mp = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK);
+ mcp = (char *)(void *)PHYS_TO_DMAP(mp->m_epg_pa[0]);
+ extpg = 0;
+ extpgsiz = PAGE_SIZE;
+ } else {
+ if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
+ clflg = 1;
+ else
+ clflg = 0;
+ if (clflg != 0)
+ NFSMCLGET(mp, M_WAITOK);
+ else
+ NFSMGET(mp);
+ mcp = mtod(mp, char *);
+ }
mp->m_len = 0;
firstmp = mp2 = mp;
+ rem = NFSM_RNDUP(siz) - siz;
while (siz > 0) {
left = uiop->uio_iov->iov_len;
uiocp = uiop->uio_iov->iov_base;
@@ -187,25 +196,40 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu
left = siz;
uiosiz = left;
while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- if (clflg)
- NFSMCLGET(mp, M_WAITOK);
- else
- NFSMGET(mp);
- mp->m_len = 0;
- mp2->m_next = mp;
- mp2 = mp;
+ if (maxext > 0)
+ mlen = extpgsiz;
+ else
mlen = M_TRAILINGSPACE(mp);
+ if (mlen == 0) {
+ if (maxext > 0) {
+ mp = nfsm_add_ext_pgs(mp, maxext,
+ &extpg);
+ mlen = extpgsiz = PAGE_SIZE;
+ mcp = (char *)(void *)PHYS_TO_DMAP(
+ mp->m_epg_pa[extpg]);
+ } else {
+ if (clflg)
+ NFSMCLGET(mp, M_WAITOK);
+ else
+ NFSMGET(mp);
+ mcp = mtod(mp, char *);
+ mlen = M_TRAILINGSPACE(mp);
+ mp->m_len = 0;
+ mp2->m_next = mp;
+ mp2 = mp;
+ }
}
xfer = (left > mlen) ? mlen : left;
if (uiop->uio_segflg == UIO_SYSSPACE)
- NFSBCOPY(uiocp, mtod(mp, caddr_t) +
- mp->m_len, xfer);
+ NFSBCOPY(uiocp, mcp, xfer);
else
- copyin(uiocp, mtod(mp, caddr_t) +
- mp->m_len, xfer);
+ copyin(uiocp, mcp, xfer);
mp->m_len += xfer;
+ mcp += xfer;
+ if (maxext > 0) {
+ extpgsiz -= xfer;
+ mp->m_epg_last_len += xfer;
+ }
left -= xfer;
uiocp += xfer;
uiop->uio_offset += xfer;
@@ -217,10 +241,16 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu
uiop->uio_iov->iov_len -= uiosiz;
siz -= uiosiz;
}
- if (cpp != NULL)
- *cpp = mtod(mp, caddr_t) + mp->m_len;
- if (mbp != NULL)
- *mbp = mp;
+ if (rem > 0) {
+ KASSERT((mp->m_flags & M_EXTPG) != 0 ||
+ rem <= M_TRAILINGSPACE(mp),
+ ("nfsm_uiombuflist: no space for padding"));
+ for (i = 0; i < rem; i++)
+ *mcp++ = '\0';
+ mp->m_len += rem;
+ if (maxext > 0)
+ mp->m_epg_last_len += rem;
+ }
return (firstmp);
}
Modified: projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 01:25:57 2020 (r363469)
+++ projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 02:19:00 2020 (r363470)
@@ -160,7 +160,6 @@ static int nfscl_dofflayoutio(vnode_t, struct uio *, i
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
-static struct mbuf *nfsm_copym(struct mbuf *, int, int);
static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
struct ucred *, NFSPROC_T *);
@@ -222,6 +221,7 @@ static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off
struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *);
static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,
int, struct nfsvattr *, int *, struct ucred *);
+static struct mbuf *nfsm_split(struct mbuf *, uint64_t);
int nfs_pnfsio(task_fn_t *, void *);
@@ -5759,7 +5759,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
struct nfscllayout *layp;
struct nfscldevinfo *dip;
struct nfsclflayout *rflp;
- struct mbuf *m;
+ struct mbuf *m, *m2;
struct nfsclwritedsdorpc *drpc, *tdrpc;
nfsv4stateid_t stateid;
struct ucred *newcred;
@@ -5865,7 +5865,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
uiop->uio_iov->iov_base;
iovlen = uiop->uio_iov->iov_len;
m = nfsm_uiombuflist(uiop, len,
- NULL, NULL);
+ 0);
}
tdrpc = drpc = malloc(sizeof(*drpc) *
(mirrorcnt - 1), M_TEMP, M_WAITOK |
@@ -5873,6 +5873,13 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
}
}
for (i = firstmirror; i < mirrorcnt && error == 0; i++){
+ m2 = NULL;
+ if (m != NULL && i < mirrorcnt - 1)
+ m2 = m_copym(m, 0, M_COPYALL, M_WAITOK);
+ else {
+ m2 = m;
+ m = NULL;
+ }
if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0) {
dev = rflp->nfsfl_ffm[i].dev;
dip = nfscl_getdevinfo(nmp->nm_clp, dev,
@@ -5889,7 +5896,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
uiop, iomode, must_commit,
&eof, &stateid, rwaccess,
dip, layp, rflp, off, xfer,
- i, docommit, m, tdrpc,
+ i, docommit, m2, tdrpc,
newcred, p);
else
error = nfscl_doflayoutio(vp,
@@ -5898,8 +5905,11 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
dip, layp, rflp, off, xfer,
docommit, newcred, p);
nfscl_reldevinfo(dip);
- } else
+ } else {
+ if (m2 != NULL)
+ m_freem(m2);
error = EIO;
+ }
tdrpc++;
}
if (m != NULL)
@@ -5965,38 +5975,6 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
}
/*
- * Make a copy of the mbuf chain and add an mbuf for null padding, as required.
- */
-static struct mbuf *
-nfsm_copym(struct mbuf *m, int off, int xfer)
-{
- struct mbuf *m2, *m3, *m4;
- uint32_t *tl;
- int rem;
-
- m2 = m_copym(m, off, xfer, M_WAITOK);
- rem = NFSM_RNDUP(xfer) - xfer;
- if (rem > 0) {
- /*
- * The zero padding to a multiple of 4 bytes is required by
- * the XDR. So that the mbufs copied by reference aren't
- * modified, add an mbuf with the zero'd bytes to the list.
- * rem will be a maximum of 3, so one zero'd uint32_t is
- * sufficient.
- */
- m3 = m2;
- while (m3->m_next != NULL)
- m3 = m3->m_next;
- NFSMGET(m4);
- tl = mtod(m4, uint32_t *);
- *tl = 0;
- m4->m_len = rem;
- m3->m_next = m4;
- }
- return (m2);
-}
-
-/*
* Find a file layout that will handle the first bytes of the requested
* range and return the information from it needed to the I/O operation.
*/
@@ -6151,17 +6129,17 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
uint64_t len, int mirror, int docommit, struct mbuf *mp,
struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
{
- uint64_t transfer, xfer;
- int error, rel_off;
+ uint64_t xfer;
+ int error;
struct nfsnode *np;
struct nfsfh *fhp;
struct nfsclds **dspp;
struct ucred *tcred;
- struct mbuf *m;
+ struct mbuf *m, *m2;
+ uint32_t copylen;
np = VTONFS(vp);
error = 0;
- rel_off = 0;
NFSCL_DEBUG(4, "nfscl_dofflayoutio: off=%ju len=%ju\n", (uintmax_t)off,
(uintmax_t)len);
/* Loop around, doing I/O for each stripe unit. */
@@ -6179,14 +6157,31 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
} else
tcred = cred;
if (rwflag == NFSV4OPEN_ACCESSREAD)
- transfer = dp->nfsdi_rsize;
- else
- transfer = dp->nfsdi_wsize;
+ copylen = dp->nfsdi_rsize;
+ else {
+ copylen = dp->nfsdi_wsize;
+ if (len > copylen && mp != NULL) {
+ /*
+ * When a mirrored configuration needs to do
+ * multiple writes to each mirror, all writes
+ * except the last one must be a multiple of
+ * 4 bytes. This is required so that the XDR
+ * does not need padding.
+ * If possible, clip the size to an exact
+ * multiple of the mbuf length, so that the
+ * split will be on an mbuf boundary.
+ */
+ copylen &= 0xfffffffc;
+ if (copylen > mp->m_len)
+ copylen = copylen / mp->m_len *
+ mp->m_len;
+ }
+ }
NFSLOCKNODE(np);
np->n_flag |= NDSCOMMIT;
NFSUNLOCKNODE(np);
- if (len > transfer && docommit == 0)
- xfer = transfer;
+ if (len > copylen && docommit == 0)
+ xfer = copylen;
else
xfer = len;
if (docommit != 0) {
@@ -6247,31 +6242,41 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
NFSUNLOCKCLSTATE();
}
} else {
- m = nfsm_copym(mp, rel_off, xfer);
- NFSCL_DEBUG(4, "mcopy reloff=%d xfer=%jd\n",
- rel_off, (uintmax_t)xfer);
+ m = mp;
+ if (xfer < len) {
+ /* The mbuf list must be split. */
+ m2 = nfsm_split(mp, xfer);
+ if (m2 != NULL)
+ mp = m2;
+ else {
+ m_freem(mp);
+ error = EIO;
+ }
+ }
+ NFSCL_DEBUG(4, "mcopy len=%jd xfer=%jd\n",
+ (uintmax_t)len, (uintmax_t)xfer);
/*
- * Do the writes after the first loop iteration
- * and the write for the last mirror via this
+ * Do last write to a mirrored DS with this
* thread.
- * This loop only iterates for small values
- * of nfsdi_wsize, which may never occur in
- * practice. However, the drpc is completely
- * used by the first iteration and, as such,
- * cannot be used after that.
*/
- if (mirror < flp->nfsfl_mirrorcnt - 1 &&
- rel_off == 0)
- error = nfsio_writedsmir(vp, iomode,
- must_commit, stateidp, *dspp, off,
- xfer, fhp, m, dp->nfsdi_vers,
- dp->nfsdi_minorvers, drpc, tcred,
- p);
- else
- error = nfsrpc_writedsmir(vp, iomode,
- must_commit, stateidp, *dspp, off,
- xfer, fhp, m, dp->nfsdi_vers,
- dp->nfsdi_minorvers, tcred, p);
+ if (error == 0) {
+ if (mirror < flp->nfsfl_mirrorcnt - 1)
+ error = nfsio_writedsmir(vp,
+ iomode, must_commit,
+ stateidp, *dspp, off,
+ xfer, fhp, m,
+ dp->nfsdi_vers,
+ dp->nfsdi_minorvers, drpc,
+ tcred, p);
+ else
+ error = nfsrpc_writedsmir(vp,
+ iomode, must_commit,
+ stateidp, *dspp, off,
+ xfer, fhp, m,
+ dp->nfsdi_vers,
+ dp->nfsdi_minorvers, tcred,
+ p);
+ }
NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
if (error != 0 && error != EACCES && error !=
ESTALE) {
@@ -6286,7 +6291,6 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
if (error == 0) {
len -= xfer;
off += xfer;
- rel_off += xfer;
}
if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0)
NFSFREECRED(tcred);
@@ -6544,12 +6548,6 @@ nfsrpc_writedsmir(vnode_t vp, int *iomode, int *must_c
if (len > 0) {
/* Put data in mbuf chain. */
nd->nd_mb->m_next = m;
- /* Set nd_mb and nd_bpos to end of data. */
- while (m->m_next != NULL)
- m = m->m_next;
- nd->nd_mb = m;
- nd->nd_bpos = mtod(m, char *) + m->m_len;
- NFSCL_DEBUG(4, "nfsrpc_writedsmir: lastmb len=%d\n", m->m_len);
}
nrp = dsp->nfsclds_sockp;
if (nrp == NULL)
@@ -8626,3 +8624,103 @@ nfsmout:
return (error);
}
+/*
+ * Split an mbuf list. For non-M_EXTPG mbufs, just use m_split().
+ */
+static struct mbuf *
+nfsm_split(struct mbuf *mp, uint64_t xfer)
+{
+ struct mbuf *m, *m2;
+ vm_page_t pg;
+ int i, j, left, pgno, plen, trim;
+ char *cp, *cp2;
+
+ if ((mp->m_flags & M_EXTPG) == 0) {
+ m = m_split(mp, xfer, M_WAITOK);
+ return (m);
+ }
+
+ /* Find the correct mbuf to split at. */
+ for (m = mp; m != NULL && xfer > m->m_len; m = m->m_next)
+ xfer -= m->m_len;
+ if (m == NULL)
+ return (NULL);
+
+ /* If xfer == m->m_len, we can just split the mbuf list. */
+ if (xfer == m->m_len) {
+ m2 = m->m_next;
+ m->m_next = NULL;
+ return (m2);
+ }
+
+ /* Find the page to split at. */
+ pgno = 0;
+ left = xfer;
+ do {
+ if (pgno == 0)
+ plen = m_epg_pagelen(m, 0, m->m_epg_1st_off);
+ else
+ plen = m_epg_pagelen(m, pgno, 0);
+ if (left <= plen)
+ break;
+ left -= plen;
+ pgno++;
+ } while (pgno < m->m_epg_npgs);
+ if (pgno == m->m_epg_npgs)
+ panic("nfsm_split: eroneous ext_pgs mbuf");
+
+ m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs);
+ m2->m_epg_flags |= EPG_FLAG_ANON;
+
+ /*
+ * If left < plen, allocate a new page for the new mbuf
+ * and copy the data after left in the page to this new
+ * page.
+ */
+ if (left < plen) {
+ do {
+ pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP |
+ VM_ALLOC_WIRED);
+ if (pg == NULL)
+ vm_wait(NULL);
+ } while (pg == NULL);
+ m2->m_epg_pa[0] = VM_PAGE_TO_PHYS(pg);
+ m2->m_epg_npgs = 1;
+
+ /* Copy the data after left to the new page. */
+ trim = plen - left;
+ cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]);
+ if (pgno == 0)
+ cp += m->m_epg_1st_off;
+ cp += left;
+ cp2 = (char *)(void *)PHYS_TO_DMAP(m2->m_epg_pa[0]);
+ if (pgno == m->m_epg_npgs - 1)
+ m2->m_epg_last_len = trim;
+ else {
+ cp2 += PAGE_SIZE - trim;
+ m2->m_epg_1st_off = PAGE_SIZE - trim;
+ m2->m_epg_last_len = m->m_epg_last_len;
+ }
+ memcpy(cp2, cp, trim);
+ m2->m_len = trim;
+ } else {
+ m2->m_len = 0;
+ m2->m_epg_last_len = m->m_epg_last_len;
+ }
+
+ /* Move the pages beyond pgno to the new mbuf. */
+ for (i = pgno + 1, j = m2->m_epg_npgs; i < m->m_epg_npgs; i++, j++) {
+ m2->m_epg_pa[j] = m->m_epg_pa[i];
+ /* Never moves page 0. */
+ m2->m_len += m_epg_pagelen(m, i, 0);
+ }
+ m2->m_epg_npgs = j;
+ m->m_epg_npgs = pgno + 1;
+ m->m_epg_last_len = left;
+ m->m_len = xfer;
+
+ m2->m_next = m->m_next;
+ m->m_next = NULL;
+ return (m2);
+}
More information about the svn-src-projects
mailing list