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:
parent
49f526501d
commit
2bad64241c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=335286
@ -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 *);
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user