Modify writing to mirrored pNFS DSs to prepare for use of ext_pgs mbufs.
This patch modifies writing to mirrored pNFS DSs slightly so that there is only one m_copym() call for a mirrored pair instead of two of them. This call replaces the custom nfsm_copym() call, which is no longer needed and deleted by this patch. The patch does introduce a new nfsm_split() function that only calls m_split() for the non-ext_pgs case. The semantics of nfsm_uiombuflist() is changed to include code that nul pads the generated mbuf list. This was done by nfsm_copym() prior to this patch. The main reason for this change is that it allows the data to be a list of ext_pgs mbufs, since the m_copym() is for the entire mbuf list. This support will be added in a future commit. This patch only affects writing to mirrored flexible file layout pNFS servers.
This commit is contained in:
parent
a1119d08b9
commit
9516bcdfb4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363437
@ -164,9 +164,9 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
|
|||||||
{
|
{
|
||||||
char *uiocp;
|
char *uiocp;
|
||||||
struct mbuf *mp, *mp2, *firstmp;
|
struct mbuf *mp, *mp2, *firstmp;
|
||||||
int xfer, left, mlen;
|
int i, left, mlen, rem, xfer;
|
||||||
int uiosiz, clflg;
|
int uiosiz, clflg;
|
||||||
char *tcp;
|
char *mcp, *tcp;
|
||||||
|
|
||||||
KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
|
KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
|
||||||
|
|
||||||
@ -179,7 +179,9 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
|
|||||||
else
|
else
|
||||||
NFSMGET(mp);
|
NFSMGET(mp);
|
||||||
mp->m_len = 0;
|
mp->m_len = 0;
|
||||||
|
mcp = mtod(mp, char *);
|
||||||
firstmp = mp2 = mp;
|
firstmp = mp2 = mp;
|
||||||
|
rem = NFSM_RNDUP(siz) - siz;
|
||||||
while (siz > 0) {
|
while (siz > 0) {
|
||||||
left = uiop->uio_iov->iov_len;
|
left = uiop->uio_iov->iov_len;
|
||||||
uiocp = uiop->uio_iov->iov_base;
|
uiocp = uiop->uio_iov->iov_base;
|
||||||
@ -194,18 +196,18 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
|
|||||||
else
|
else
|
||||||
NFSMGET(mp);
|
NFSMGET(mp);
|
||||||
mp->m_len = 0;
|
mp->m_len = 0;
|
||||||
|
mcp = mtod(mp, char *);
|
||||||
mp2->m_next = mp;
|
mp2->m_next = mp;
|
||||||
mp2 = mp;
|
mp2 = mp;
|
||||||
mlen = M_TRAILINGSPACE(mp);
|
mlen = M_TRAILINGSPACE(mp);
|
||||||
}
|
}
|
||||||
xfer = (left > mlen) ? mlen : left;
|
xfer = (left > mlen) ? mlen : left;
|
||||||
if (uiop->uio_segflg == UIO_SYSSPACE)
|
if (uiop->uio_segflg == UIO_SYSSPACE)
|
||||||
NFSBCOPY(uiocp, mtod(mp, caddr_t) +
|
NFSBCOPY(uiocp, mcp, xfer);
|
||||||
mp->m_len, xfer);
|
|
||||||
else
|
else
|
||||||
copyin(uiocp, mtod(mp, caddr_t) +
|
copyin(uiocp, mcp, xfer);
|
||||||
mp->m_len, xfer);
|
|
||||||
mp->m_len += xfer;
|
mp->m_len += xfer;
|
||||||
|
mcp += xfer;
|
||||||
left -= xfer;
|
left -= xfer;
|
||||||
uiocp += xfer;
|
uiocp += xfer;
|
||||||
uiop->uio_offset += xfer;
|
uiop->uio_offset += xfer;
|
||||||
@ -217,6 +219,13 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
|
|||||||
uiop->uio_iov->iov_len -= uiosiz;
|
uiop->uio_iov->iov_len -= uiosiz;
|
||||||
siz -= uiosiz;
|
siz -= uiosiz;
|
||||||
}
|
}
|
||||||
|
if (rem > 0) {
|
||||||
|
KASSERT(rem <= M_TRAILINGSPACE(mp),
|
||||||
|
("nfsm_uiombuflist: no space for padding"));
|
||||||
|
for (i = 0; i < rem; i++)
|
||||||
|
*mcp++ = '\0';
|
||||||
|
mp->m_len += rem;
|
||||||
|
}
|
||||||
if (cpp != NULL)
|
if (cpp != NULL)
|
||||||
*cpp = mtod(mp, caddr_t) + mp->m_len;
|
*cpp = mtod(mp, caddr_t) + mp->m_len;
|
||||||
if (mbp != NULL)
|
if (mbp != NULL)
|
||||||
|
@ -158,7 +158,6 @@ static int nfscl_dofflayoutio(vnode_t, struct uio *, int *, int *, int *,
|
|||||||
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
|
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
|
||||||
struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
|
struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
|
||||||
struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
|
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 *,
|
static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
|
||||||
struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
|
struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
|
||||||
struct ucred *, NFSPROC_T *);
|
struct ucred *, NFSPROC_T *);
|
||||||
@ -220,6 +219,7 @@ static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off_t, size_t *,
|
|||||||
struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *);
|
struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *);
|
||||||
static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,
|
static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,
|
||||||
int, struct nfsvattr *, int *, struct ucred *);
|
int, struct nfsvattr *, int *, struct ucred *);
|
||||||
|
static struct mbuf *nfsm_split(struct mbuf *, uint64_t);
|
||||||
|
|
||||||
int nfs_pnfsio(task_fn_t *, void *);
|
int nfs_pnfsio(task_fn_t *, void *);
|
||||||
|
|
||||||
@ -5756,7 +5756,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
struct nfscllayout *layp;
|
struct nfscllayout *layp;
|
||||||
struct nfscldevinfo *dip;
|
struct nfscldevinfo *dip;
|
||||||
struct nfsclflayout *rflp;
|
struct nfsclflayout *rflp;
|
||||||
struct mbuf *m;
|
struct mbuf *m, *m2;
|
||||||
struct nfsclwritedsdorpc *drpc, *tdrpc;
|
struct nfsclwritedsdorpc *drpc, *tdrpc;
|
||||||
nfsv4stateid_t stateid;
|
nfsv4stateid_t stateid;
|
||||||
struct ucred *newcred;
|
struct ucred *newcred;
|
||||||
@ -5870,6 +5870,13 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = firstmirror; i < mirrorcnt && error == 0; i++){
|
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) {
|
if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0) {
|
||||||
dev = rflp->nfsfl_ffm[i].dev;
|
dev = rflp->nfsfl_ffm[i].dev;
|
||||||
dip = nfscl_getdevinfo(nmp->nm_clp, dev,
|
dip = nfscl_getdevinfo(nmp->nm_clp, dev,
|
||||||
@ -5886,7 +5893,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
uiop, iomode, must_commit,
|
uiop, iomode, must_commit,
|
||||||
&eof, &stateid, rwaccess,
|
&eof, &stateid, rwaccess,
|
||||||
dip, layp, rflp, off, xfer,
|
dip, layp, rflp, off, xfer,
|
||||||
i, docommit, m, tdrpc,
|
i, docommit, m2, tdrpc,
|
||||||
newcred, p);
|
newcred, p);
|
||||||
else
|
else
|
||||||
error = nfscl_doflayoutio(vp,
|
error = nfscl_doflayoutio(vp,
|
||||||
@ -5895,8 +5902,11 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
dip, layp, rflp, off, xfer,
|
dip, layp, rflp, off, xfer,
|
||||||
docommit, newcred, p);
|
docommit, newcred, p);
|
||||||
nfscl_reldevinfo(dip);
|
nfscl_reldevinfo(dip);
|
||||||
} else
|
} else {
|
||||||
|
if (m2 != NULL)
|
||||||
|
m_freem(m2);
|
||||||
error = EIO;
|
error = EIO;
|
||||||
|
}
|
||||||
tdrpc++;
|
tdrpc++;
|
||||||
}
|
}
|
||||||
if (m != NULL)
|
if (m != NULL)
|
||||||
@ -5961,38 +5971,6 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
* 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.
|
* range and return the information from it needed to the I/O operation.
|
||||||
@ -6148,17 +6126,17 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
uint64_t len, int mirror, int docommit, struct mbuf *mp,
|
uint64_t len, int mirror, int docommit, struct mbuf *mp,
|
||||||
struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
|
struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
|
||||||
{
|
{
|
||||||
uint64_t transfer, xfer;
|
uint64_t xfer;
|
||||||
int error, rel_off;
|
int error;
|
||||||
struct nfsnode *np;
|
struct nfsnode *np;
|
||||||
struct nfsfh *fhp;
|
struct nfsfh *fhp;
|
||||||
struct nfsclds **dspp;
|
struct nfsclds **dspp;
|
||||||
struct ucred *tcred;
|
struct ucred *tcred;
|
||||||
struct mbuf *m;
|
struct mbuf *m, *m2;
|
||||||
|
uint32_t copylen;
|
||||||
|
|
||||||
np = VTONFS(vp);
|
np = VTONFS(vp);
|
||||||
error = 0;
|
error = 0;
|
||||||
rel_off = 0;
|
|
||||||
NFSCL_DEBUG(4, "nfscl_dofflayoutio: off=%ju len=%ju\n", (uintmax_t)off,
|
NFSCL_DEBUG(4, "nfscl_dofflayoutio: off=%ju len=%ju\n", (uintmax_t)off,
|
||||||
(uintmax_t)len);
|
(uintmax_t)len);
|
||||||
/* Loop around, doing I/O for each stripe unit. */
|
/* Loop around, doing I/O for each stripe unit. */
|
||||||
@ -6176,14 +6154,31 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
} else
|
} else
|
||||||
tcred = cred;
|
tcred = cred;
|
||||||
if (rwflag == NFSV4OPEN_ACCESSREAD)
|
if (rwflag == NFSV4OPEN_ACCESSREAD)
|
||||||
transfer = dp->nfsdi_rsize;
|
copylen = dp->nfsdi_rsize;
|
||||||
else
|
else {
|
||||||
transfer = dp->nfsdi_wsize;
|
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);
|
NFSLOCKNODE(np);
|
||||||
np->n_flag |= NDSCOMMIT;
|
np->n_flag |= NDSCOMMIT;
|
||||||
NFSUNLOCKNODE(np);
|
NFSUNLOCKNODE(np);
|
||||||
if (len > transfer && docommit == 0)
|
if (len > copylen && docommit == 0)
|
||||||
xfer = transfer;
|
xfer = copylen;
|
||||||
else
|
else
|
||||||
xfer = len;
|
xfer = len;
|
||||||
if (docommit != 0) {
|
if (docommit != 0) {
|
||||||
@ -6244,31 +6239,41 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
NFSUNLOCKCLSTATE();
|
NFSUNLOCKCLSTATE();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m = nfsm_copym(mp, rel_off, xfer);
|
m = mp;
|
||||||
NFSCL_DEBUG(4, "mcopy reloff=%d xfer=%jd\n",
|
if (xfer < len) {
|
||||||
rel_off, (uintmax_t)xfer);
|
/* 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
|
* Do last write to a mirrored DS with this
|
||||||
* and the write for the last mirror via this
|
|
||||||
* thread.
|
* 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 &&
|
if (error == 0) {
|
||||||
rel_off == 0)
|
if (mirror < flp->nfsfl_mirrorcnt - 1)
|
||||||
error = nfsio_writedsmir(vp, iomode,
|
error = nfsio_writedsmir(vp,
|
||||||
must_commit, stateidp, *dspp, off,
|
iomode, must_commit,
|
||||||
xfer, fhp, m, dp->nfsdi_vers,
|
stateidp, *dspp, off,
|
||||||
dp->nfsdi_minorvers, drpc, tcred,
|
xfer, fhp, m,
|
||||||
p);
|
dp->nfsdi_vers,
|
||||||
|
dp->nfsdi_minorvers, drpc,
|
||||||
|
tcred, p);
|
||||||
else
|
else
|
||||||
error = nfsrpc_writedsmir(vp, iomode,
|
error = nfsrpc_writedsmir(vp,
|
||||||
must_commit, stateidp, *dspp, off,
|
iomode, must_commit,
|
||||||
xfer, fhp, m, dp->nfsdi_vers,
|
stateidp, *dspp, off,
|
||||||
dp->nfsdi_minorvers, tcred, p);
|
xfer, fhp, m,
|
||||||
|
dp->nfsdi_vers,
|
||||||
|
dp->nfsdi_minorvers, tcred,
|
||||||
|
p);
|
||||||
|
}
|
||||||
NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
|
NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
|
||||||
if (error != 0 && error != EACCES && error !=
|
if (error != 0 && error != EACCES && error !=
|
||||||
ESTALE) {
|
ESTALE) {
|
||||||
@ -6283,7 +6288,6 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
|||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
len -= xfer;
|
len -= xfer;
|
||||||
off += xfer;
|
off += xfer;
|
||||||
rel_off += xfer;
|
|
||||||
}
|
}
|
||||||
if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0)
|
if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0)
|
||||||
NFSFREECRED(tcred);
|
NFSFREECRED(tcred);
|
||||||
@ -8615,3 +8619,14 @@ nfsrpc_listextattr(vnode_t vp, uint64_t *cookiep, struct uio *uiop,
|
|||||||
return (error);
|
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;
|
||||||
|
|
||||||
|
m = m_split(mp, xfer, M_WAITOK);
|
||||||
|
return (m);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user