Add support to the NFSv4.1/pNFS client for commits through the DS.

A NFSv4.1/pNFS server using File Layout can specify that Commit operations
are to be done against the DS instead of MDS. Since no extant pNFS
server did this, the code was untested and "#ifdef notyet".
The FreeBSD pNFS server I am developing does specify that Commits be done
through the DS, so the code has been enabled/tested.
This patch should only affect the case of a pNFS server that specfies
Commits through the DS.

PR:		219551
MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2017-06-26 00:43:04 +00:00
parent 8a89ca9425
commit 81b07aac10
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=320345
5 changed files with 73 additions and 30 deletions

View File

@ -490,7 +490,7 @@ int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, int, int, uint32_t,
int, uint64_t, uint64_t, nfsv4stateid_t *, int, uint32_t *, struct ucred *,
NFSPROC_T *, void *);
int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *);
int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t,
int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, int,
struct ucred *, NFSPROC_T *);
int nfscl_findlayoutforio(struct nfscllayout *, uint64_t, uint32_t,
struct nfsclflayout **);

View File

@ -259,10 +259,12 @@ ncl_inactive(struct vop_inactive_args *ap)
/*
* NMODIFIED means that there might be dirty/stale buffers
* associated with the NFS vnode. None of the other flags are
* meaningful after the vnode is unused.
* associated with the NFS vnode.
* NDSCOMMIT means that the file is on a pNFS server and commits
* should be done to the DS.
* None of the other flags are meaningful after the vnode is unused.
*/
np->n_flag &= NMODIFIED;
np->n_flag &= (NMODIFIED | NDSCOMMIT);
mtx_unlock(&np->n_mtx);
return (0);
}

View File

@ -114,7 +114,8 @@ static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_storage *,
static void nfscl_initsessionslots(struct nfsclsession *);
static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
struct nfsclflayout *, uint64_t, uint64_t, struct ucred *, NFSPROC_T *);
struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *,
NFSPROC_T *);
static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
struct nfsclds *, uint64_t, int, struct nfsfh *, struct ucred *,
NFSPROC_T *);
@ -123,10 +124,8 @@ static int nfsrpc_writeds(vnode_t, struct uio *, int *, int *,
struct nfsfh *, int, struct ucred *, NFSPROC_T *);
static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
struct nfsclds *, struct nfsclds **);
#ifdef notyet
static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
struct nfsfh *, struct ucred *, NFSPROC_T *, void *);
#endif
struct nfsfh *, struct ucred *, NFSPROC_T *);
static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
uint64_t, uint64_t, nfsv4stateid_t *, int, int);
static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *,
@ -5439,7 +5438,7 @@ nfscl_initsessionslots(struct nfsclsession *sep)
*/
int
nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
uint32_t rwaccess, struct ucred *cred, NFSPROC_T *p)
uint32_t rwaccess, int docommit, struct ucred *cred, NFSPROC_T *p)
{
struct nfsnode *np = VTONFS(vp);
struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
@ -5523,7 +5522,8 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
if (dip != NULL) {
error = nfscl_doflayoutio(vp, uiop, iomode,
must_commit, &eof, &stateid, rwaccess, dip,
layp, rflp, off, xfer, newcred, p);
layp, rflp, off, xfer, docommit, newcred,
p);
nfscl_reldevinfo(dip);
lastbyte = off + xfer - 1;
if (error == 0) {
@ -5599,10 +5599,10 @@ static int
nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo *dp,
struct nfscllayout *lyp, struct nfsclflayout *flp, uint64_t off,
uint64_t len, struct ucred *cred, NFSPROC_T *p)
uint64_t len, int docommit, struct ucred *cred, NFSPROC_T *p)
{
uint64_t io_off, rel_off, stripe_unit_size, transfer, xfer;
int commit_thru_mds, error = 0, stripe_index, stripe_pos;
int commit_thru_mds, error, stripe_index, stripe_pos;
struct nfsnode *np;
struct nfsfh *fhp;
struct nfsclds **dspp;
@ -5613,12 +5613,13 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
stripe_pos = (rel_off / stripe_unit_size + flp->nfsfl_stripe1) %
dp->nfsdi_stripecnt;
transfer = stripe_unit_size - (rel_off % stripe_unit_size);
error = 0;
/* Loop around, doing I/O for each stripe unit. */
while (len > 0 && error == 0) {
stripe_index = nfsfldi_stripeindex(dp, stripe_pos);
dspp = nfsfldi_addr(dp, stripe_index);
if (len > transfer)
if (len > transfer && docommit == 0)
xfer = transfer;
else
xfer = len;
@ -5642,11 +5643,33 @@ nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
fhp = np->n_fhp;
io_off = off;
}
if ((flp->nfsfl_util & NFSFLAYUTIL_COMMIT_THRU_MDS) != 0)
if ((flp->nfsfl_util & NFSFLAYUTIL_COMMIT_THRU_MDS) != 0) {
commit_thru_mds = 1;
else
if (docommit != 0)
error = EIO;
} else {
commit_thru_mds = 0;
if (rwflag == FREAD)
mtx_lock(&np->n_mtx);
np->n_flag |= NDSCOMMIT;
mtx_unlock(&np->n_mtx);
}
if (docommit != 0) {
if (error == 0)
error = nfsrpc_commitds(vp, io_off, xfer,
*dspp, fhp, cred, p);
if (error == 0) {
/*
* Set both eof and uio_resid = 0 to end any
* loops.
*/
*eofp = 1;
uiop->uio_resid = 0;
} else {
mtx_lock(&np->n_mtx);
np->n_flag &= ~NDSCOMMIT;
mtx_unlock(&np->n_mtx);
}
} else if (rwflag == FREAD)
error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
io_off, xfer, fhp, cred, p);
else {
@ -5882,13 +5905,12 @@ nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp,
return (NFSDSP_NOTFOUND);
}
#ifdef notyet
/*
* NFS commit rpc to a DS.
* NFS commit rpc to a NFSv4.1 DS.
*/
static int
nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
struct nfsfh *fhp, struct ucred *cred, NFSPROC_T *p, void *stuff)
struct nfsfh *fhp, struct ucred *cred, NFSPROC_T *p)
{
uint32_t *tl;
struct nfsrv_descript nfsd, *nd = &nfsd;
@ -5896,6 +5918,7 @@ nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
struct nfssockreq *nrp;
int error;
nd->nd_mrep = NULL;
nfscl_reqstart(nd, NFSPROC_COMMITDS, nmp, fhp->nfh_fh, fhp->nfh_len,
NULL, &dsp->nfsclds_sess);
NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
@ -5908,7 +5931,7 @@ nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
nrp = &nmp->nm_sockreq;
error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
if (error)
if (error != 0)
return (error);
if (nd->nd_repstat == 0) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
@ -5925,7 +5948,6 @@ nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
mbuf_freem(nd->nd_mrep);
return (error);
}
#endif
/*
* Set up the XDR arguments for the LayoutGet operation.

View File

@ -1367,7 +1367,7 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
attrflag = 0;
if (NFSHASPNFS(nmp))
error = nfscl_doiods(vp, uiop, NULL, NULL,
NFSV4OPEN_ACCESSREAD, cred, uiop->uio_td);
NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
if (error != 0)
error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
@ -1398,7 +1398,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
attrflag = 0;
if (NFSHASPNFS(nmp))
error = nfscl_doiods(vp, uiop, iomode, must_commit,
NFSV4OPEN_ACCESSWRITE, cred, uiop->uio_td);
NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
if (error != 0)
error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
@ -2555,16 +2555,34 @@ ncl_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
{
struct nfsvattr nfsva;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct nfsnode *np;
struct uio uio;
int error, attrflag;
mtx_lock(&nmp->nm_mtx);
if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
mtx_unlock(&nmp->nm_mtx);
return (0);
np = VTONFS(vp);
error = EIO;
attrflag = 0;
if (NFSHASPNFS(nmp) && (np->n_flag & NDSCOMMIT) != 0) {
uio.uio_offset = offset;
uio.uio_resid = cnt;
error = nfscl_doiods(vp, &uio, NULL, NULL,
NFSV4OPEN_ACCESSWRITE, 1, cred, td);
if (error != 0) {
mtx_lock(&np->n_mtx);
np->n_flag &= ~NDSCOMMIT;
mtx_unlock(&np->n_mtx);
}
}
if (error != 0) {
mtx_lock(&nmp->nm_mtx);
if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
mtx_unlock(&nmp->nm_mtx);
return (0);
}
mtx_unlock(&nmp->nm_mtx);
error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
&attrflag, NULL);
}
mtx_unlock(&nmp->nm_mtx);
error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
&attrflag, NULL);
if (attrflag != 0)
(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL,
0, 1);

View File

@ -158,6 +158,7 @@ struct nfsnode {
#define NNOLAYOUT 0x00020000 /* Can't get a layout for this file */
#define NWRITEOPENED 0x00040000 /* Has been opened for writing */
#define NHASBEENLOCKED 0x00080000 /* Has been file locked. */
#define NDSCOMMIT 0x00100000 /* Commit is done via the DS. */
/*
* Convert between nfsnode pointers and vnode pointers