Make the pNFS NFSv4.1 client return a Flexible File layout upon error.

The Flexible File layout LayoutReturn operation has argument fields where
an I/O error encountered when attempting I/O on a DS can be reported back
to the MDS.
This patch adds code to the client to do this for the Flexible File layout
mirrored case.
This patch should only affect mounts using the "pnfs" option against servers
that support the Flexible File layout.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2018-06-17 16:30:06 +00:00
parent 49f526501d
commit 2bad64241c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=335286
4 changed files with 95 additions and 16 deletions

View File

@ -528,7 +528,7 @@ int nfsrpc_layoutcommit(struct nfsmount *, uint8_t *, int, int,
NFSPROC_T *, void *);
int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, int, int, uint32_t,
int, uint64_t, uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *,
void *);
uint32_t, uint32_t, char *);
int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *);
int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, int,
struct ucred *, NFSPROC_T *);
@ -601,6 +601,7 @@ 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_rellayout(struct nfscllayout *, int);
struct nfscldevinfo *nfscl_getdevinfo(struct nfsclclient *, uint8_t *,
struct nfscldevinfo *);

View File

@ -340,6 +340,9 @@ struct nfsclrecalllayout {
int nfsrecly_recalltype;
uint32_t nfsrecly_iomode;
uint32_t nfsrecly_stateseqid;
uint32_t nfsrecly_stat;
uint32_t nfsrecly_op;
char nfsrecly_devid[NFSX_V4DEVICEID];
};
/*

View File

@ -5203,10 +5203,11 @@ int
nfsrpc_layoutreturn(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
int layouttype, uint32_t iomode, int layoutreturn, uint64_t offset,
uint64_t len, nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
void *stuff)
uint32_t stat, uint32_t op, char *devid)
{
uint32_t *tl;
struct nfsrv_descript nfsd, *nd = &nfsd;
uint64_t tu64;
int error;
nfscl_reqstart(nd, NFSPROC_LAYOUTRETURN, nmp, fh, fhlen, NULL, NULL,
@ -5234,11 +5235,32 @@ nfsrpc_layoutreturn(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
if (layouttype == NFSLAYOUT_NFSV4_1_FILES)
*tl = txdr_unsigned(0);
else if (layouttype == NFSLAYOUT_FLEXFILE) {
*tl = txdr_unsigned(2 * NFSX_UNSIGNED);
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
/* No ioerrs or stats yet. */
*tl++ = 0;
*tl = 0;
if (stat != 0) {
*tl = txdr_unsigned(2 * NFSX_HYPER +
NFSX_STATEID + NFSX_V4DEVICEID + 5 *
NFSX_UNSIGNED);
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER +
NFSX_STATEID + NFSX_V4DEVICEID + 5 *
NFSX_UNSIGNED);
*tl++ = txdr_unsigned(1); /* One error. */
tu64 = 0; /* Offset. */
txdr_hyper(tu64, tl); tl += 2;
tu64 = UINT64_MAX; /* Length. */
txdr_hyper(tu64, tl); tl += 2;
NFSBCOPY(stateidp, tl, NFSX_STATEID);
tl += (NFSX_STATEID / NFSX_UNSIGNED);
*tl++ = txdr_unsigned(1); /* One error. */
NFSBCOPY(devid, tl, NFSX_V4DEVICEID);
tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
*tl++ = txdr_unsigned(stat);
*tl++ = txdr_unsigned(op);
} else {
*tl = txdr_unsigned(2 * NFSX_UNSIGNED);
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
/* No ioerrs. */
*tl++ = 0;
}
*tl = 0; /* No stats yet. */
}
}
nd->nd_flag |= ND_USEGSSNAME;
@ -6017,6 +6039,12 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
error = nfsrpc_commitds(vp, off, xfer,
*dspp, fhp, dp->nfsdi_vers,
dp->nfsdi_minorvers, tcred, p);
NFSCL_DEBUG(4, "commitds=%d\n", error);
if (nfsds_failerr(error)) {
NFSCL_DEBUG(4,
"DS layreterr for commit\n");
nfscl_dserr(NFSV4OP_COMMIT, dp, lyp);
}
}
NFSCL_DEBUG(4, "aft nfsio_commitds=%d\n", error);
if (error == 0) {
@ -6031,11 +6059,16 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
np->n_flag &= ~NDSCOMMIT;
mtx_unlock(&np->n_mtx);
}
} else if (rwflag == NFSV4OPEN_ACCESSREAD)
} else if (rwflag == NFSV4OPEN_ACCESSREAD) {
error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
off, xfer, fhp, 1, dp->nfsdi_vers,
dp->nfsdi_minorvers, tcred, p);
else {
NFSCL_DEBUG(4, "readds=%d\n", error);
if (nfsds_failerr(error)) {
NFSCL_DEBUG(4, "DS layreterr for read\n");
nfscl_dserr(NFSV4OP_READ, dp, lyp);
}
} else {
if (flp->nfsfl_mirrorcnt == 1) {
error = nfsrpc_writeds(vp, uiop, iomode,
must_commit, stateidp, *dspp, off, xfer,
@ -6066,6 +6099,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)) {
NFSCL_DEBUG(4,
"DS layreterr for write\n");
nfscl_dserr(NFSV4OP_WRITE, dp, lyp);
}
}
}
NFSCL_DEBUG(4, "aft read/writeds=%d\n", error);

View File

@ -164,7 +164,7 @@ static void nfscl_emptylockowner(struct nfscllockowner *,
static void nfscl_mergeflayouts(struct nfsclflayouthead *,
struct nfsclflayouthead *);
static int nfscl_layoutrecall(int, struct nfscllayout *, uint32_t, uint64_t,
uint64_t, uint32_t, struct nfsclrecalllayout *);
uint64_t, uint32_t, uint32_t, uint32_t, char *, struct nfsclrecalllayout *);
static int nfscl_seq(uint32_t, uint32_t);
static void nfscl_layoutreturn(struct nfsmount *, struct nfscllayout *,
struct ucred *, NFSPROC_T *);
@ -2762,7 +2762,8 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
break;
(void)nfscl_layoutrecall(NFSLAYOUTRETURN_FILE,
lyp, NFSLAYOUTIOMODE_ANY, 0, UINT64_MAX,
lyp->nfsly_stateid.seqid, recallp);
lyp->nfsly_stateid.seqid, 0, 0, NULL,
recallp);
}
lyp = nlyp;
}
@ -3469,6 +3470,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
recalltype,
lyp, iomode, off,
len, stateid.seqid,
0, 0, NULL,
recallp);
recallp = NULL;
wakeup(clp);
@ -3503,6 +3505,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
lyp, iomode, 0,
UINT64_MAX,
lyp->nfsly_stateid.seqid,
0, 0, NULL,
recallp);
recallp = NULL;
gotone = 1;
@ -3526,7 +3529,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
recalltype, lyp, iomode, 0,
UINT64_MAX,
lyp->nfsly_stateid.seqid,
recallp);
0, 0, NULL, recallp);
recallp = NULL;
gotone = 1;
}
@ -4959,12 +4962,41 @@ nfscl_retoncloselayout(vnode_t vp, struct nfsclclient *clp, uint8_t *fhp,
if (!LIST_EMPTY(&lyp->nfsly_flayrw))
iomode |= NFSLAYOUTIOMODE_RW;
(void)nfscl_layoutrecall(NFSLAYOUTRETURN_FILE, lyp, iomode,
0, UINT64_MAX, lyp->nfsly_stateid.seqid, *recallpp);
0, UINT64_MAX, lyp->nfsly_stateid.seqid, 0, 0, NULL,
*recallpp);
NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
*recallpp = NULL;
}
}
/*
* Mark the layout to be recalled and with an error.
*/
void
nfscl_dserr(uint32_t op, struct nfscldevinfo *dp, struct nfscllayout *lyp)
{
struct nfsclrecalllayout *recallp;
uint32_t iomode;
recallp = malloc(sizeof(*recallp), M_NFSLAYRECALL, M_WAITOK);
iomode = 0;
NFSLOCKCLSTATE();
if ((lyp->nfsly_flags & NFSLY_RECALL) == 0) {
if (!LIST_EMPTY(&lyp->nfsly_flayread))
iomode |= NFSLAYOUTIOMODE_READ;
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,
dp->nfsdi_deviceid, recallp);
NFSUNLOCKCLSTATE();
NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
} else {
NFSUNLOCKCLSTATE();
free(recallp, M_NFSLAYRECALL);
}
}
/*
* Dereference a layout.
*/
@ -5182,8 +5214,8 @@ nfscl_freedevinfo(struct nfscldevinfo *dip)
*/
static int
nfscl_layoutrecall(int recalltype, struct nfscllayout *lyp, uint32_t iomode,
uint64_t off, uint64_t len, uint32_t stateseqid,
struct nfsclrecalllayout *recallp)
uint64_t off, uint64_t len, uint32_t stateseqid, uint32_t stat, uint32_t op,
char *devid, struct nfsclrecalllayout *recallp)
{
struct nfsclrecalllayout *rp, *orp;
@ -5192,6 +5224,10 @@ nfscl_layoutrecall(int recalltype, struct nfscllayout *lyp, uint32_t iomode,
recallp->nfsrecly_stateseqid = stateseqid;
recallp->nfsrecly_off = off;
recallp->nfsrecly_len = len;
recallp->nfsrecly_stat = stat;
recallp->nfsrecly_op = op;
if (devid != NULL)
NFSBCOPY(devid, recallp->nfsrecly_devid, NFSX_V4DEVICEID);
/*
* Order the list as file returns first, followed by fsid and any
* returns, both in increasing stateseqid order.
@ -5266,7 +5302,8 @@ nfscl_layoutreturn(struct nfsmount *nmp, struct nfscllayout *lyp,
lyp->nfsly_fhlen, 0, layouttype,
rp->nfsrecly_iomode, rp->nfsrecly_recalltype,
rp->nfsrecly_off, rp->nfsrecly_len,
&stateid, cred, p, NULL);
&stateid, cred, p, rp->nfsrecly_stat, rp->nfsrecly_op,
rp->nfsrecly_devid);
}
}