Change the NFSv4.1 pNFS client so that it returns the DS error in layoutreturn.

When the NFSv4.1 pNFS client gets an error for a DS I/O operation using a
Flexible File layout, it returns the layout with an error.
This patch changes the code slightly, so that it returns the layout for all
errors except EACCES and lets the MDS decide what to do based on the error.
It also makes a couple of changes to nfscl_layoutrecall() to ensure that
the first layoutreturn(s) will have the error in the reply.
Plus, the patch adds a wakeup() so that the "nfscl" thread won't wait 1sec
before doing the LayoutReturn.
Tested against the pNFS service.
This patch should not affect non-pNFS use of the client.
The unused "dsp" argument will be used by a future patch that disables the
connection to the DS when possible.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2018-06-22 21:25:27 +00:00
parent 9d48901e34
commit 2e35b8fe24
3 changed files with 30 additions and 10 deletions

View File

@ -601,7 +601,8 @@ int nfscl_layout(struct nfsmount *, vnode_t, u_int8_t *, int, nfsv4stateid_t *,
NFSPROC_T *);
struct nfscllayout *nfscl_getlayout(struct nfsclclient *, uint8_t *, int,
uint64_t, struct nfsclflayout **, int *);
void nfscl_dserr(uint32_t, struct nfscldevinfo *, struct nfscllayout *);
void nfscl_dserr(uint32_t, uint32_t, struct nfscldevinfo *,
struct nfscllayout *, struct nfsclds *);
void nfscl_rellayout(struct nfscllayout *, int);
struct nfscldevinfo *nfscl_getdevinfo(struct nfsclclient *, uint8_t *,
struct nfscldevinfo *);

View File

@ -6040,10 +6040,11 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
*dspp, fhp, dp->nfsdi_vers,
dp->nfsdi_minorvers, tcred, p);
NFSCL_DEBUG(4, "commitds=%d\n", error);
if (nfsds_failerr(error)) {
if (error != 0 && error != EACCES) {
NFSCL_DEBUG(4,
"DS layreterr for commit\n");
nfscl_dserr(NFSV4OP_COMMIT, dp, lyp);
nfscl_dserr(NFSV4OP_COMMIT, error, dp,
lyp, *dspp);
}
}
NFSCL_DEBUG(4, "aft nfsio_commitds=%d\n", error);
@ -6064,9 +6065,10 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
off, xfer, fhp, 1, dp->nfsdi_vers,
dp->nfsdi_minorvers, tcred, p);
NFSCL_DEBUG(4, "readds=%d\n", error);
if (nfsds_failerr(error)) {
if (error != 0 && error != EACCES) {
NFSCL_DEBUG(4, "DS layreterr for read\n");
nfscl_dserr(NFSV4OP_READ, dp, lyp);
nfscl_dserr(NFSV4OP_READ, error, dp, lyp,
*dspp);
}
} else {
if (flp->nfsfl_mirrorcnt == 1) {
@ -6099,10 +6101,11 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
xfer, fhp, m, dp->nfsdi_vers,
dp->nfsdi_minorvers, tcred, p);
NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
if (nfsds_failerr(error)) {
if (error != 0 && error != EACCES) {
NFSCL_DEBUG(4,
"DS layreterr for write\n");
nfscl_dserr(NFSV4OP_WRITE, dp, lyp);
nfscl_dserr(NFSV4OP_WRITE, error, dp,
lyp, *dspp);
}
}
}

View File

@ -4973,11 +4973,13 @@ nfscl_retoncloselayout(vnode_t vp, struct nfsclclient *clp, uint8_t *fhp,
* Mark the layout to be recalled and with an error.
*/
void
nfscl_dserr(uint32_t op, struct nfscldevinfo *dp, struct nfscllayout *lyp)
nfscl_dserr(uint32_t op, uint32_t stat, struct nfscldevinfo *dp,
struct nfscllayout *lyp, __unused struct nfsclds *dsp)
{
struct nfsclrecalllayout *recallp;
uint32_t iomode;
/* Set up the return of the layout. */
recallp = malloc(sizeof(*recallp), M_NFSLAYRECALL, M_WAITOK);
iomode = 0;
NFSLOCKCLSTATE();
@ -4987,10 +4989,10 @@ nfscl_dserr(uint32_t op, struct nfscldevinfo *dp, struct nfscllayout *lyp)
if (!LIST_EMPTY(&lyp->nfsly_flayrw))
iomode |= NFSLAYOUTIOMODE_RW;
(void)nfscl_layoutrecall(NFSLAYOUTRETURN_FILE, lyp, iomode,
0, UINT64_MAX, lyp->nfsly_stateid.seqid, NFSERR_IO, op,
0, UINT64_MAX, lyp->nfsly_stateid.seqid, stat, op,
dp->nfsdi_deviceid, recallp);
NFSUNLOCKCLSTATE();
NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
NFSCL_DEBUG(4, "nfscl_dserr recall iomode=%d\n", iomode);
} else {
NFSUNLOCKCLSTATE();
free(recallp, M_NFSLAYRECALL);
@ -5247,6 +5249,19 @@ nfscl_layoutrecall(int recalltype, struct nfscllayout *lyp, uint32_t iomode,
LIST_INSERT_BEFORE(rp, recallp, nfsrecly_list);
break;
}
/*
* Put any error return on all the file returns that will
* preceed this one.
*/
if (rp->nfsrecly_recalltype == NFSLAYOUTRETURN_FILE &&
stat != 0 && rp->nfsrecly_stat == 0) {
rp->nfsrecly_stat = stat;
rp->nfsrecly_op = op;
if (devid != NULL)
NFSBCOPY(devid, rp->nfsrecly_devid,
NFSX_V4DEVICEID);
}
}
if (rp == NULL) {
if (orp == NULL)
@ -5256,6 +5271,7 @@ nfscl_layoutrecall(int recalltype, struct nfscllayout *lyp, uint32_t iomode,
LIST_INSERT_AFTER(orp, recallp, nfsrecly_list);
}
lyp->nfsly_flags |= NFSLY_RECALL;
wakeup(lyp->nfsly_clp);
return (0);
}