diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2017-07-15 19:24:54 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2017-07-15 19:24:54 +0000 |
commit | fc5d98f046efdae2cce1406467b88855a4ce4cc4 (patch) | |
tree | 5e1415ecaae8cfb21981143ec4f72636a50ebe09 /sys/fs | |
parent | 52330ec7aba753626b0bd08623efab39659a6b89 (diff) | |
download | FreeBSD-src-fc5d98f046efdae2cce1406467b88855a4ce4cc4.zip FreeBSD-src-fc5d98f046efdae2cce1406467b88855a4ce4cc4.tar.gz |
MFC: r320345
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.
Relnotes: yes
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 2 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clnode.c | 8 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clrpcops.c | 56 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clvnops.c | 34 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfsnode.h | 1 |
5 files changed, 72 insertions, 29 deletions
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 94ee93c..da6f7a9 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -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 **); diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 3f2ea01..fe51cc9 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -261,10 +261,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); } diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 85efc75..9bb166b 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -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 *); /* * nfs null call from vfs. @@ -5531,7 +5530,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)); @@ -5615,7 +5614,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) { @@ -5691,10 +5691,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; @@ -5705,12 +5705,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; @@ -5734,11 +5735,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 { @@ -5974,13 +5997,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; @@ -5988,6 +6010,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); @@ -6000,7 +6023,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); @@ -6017,5 +6040,4 @@ nfsmout: mbuf_freem(nd->nd_mrep); return (error); } -#endif diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 513f15d..6b66137 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1376,7 +1376,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, @@ -1407,7 +1407,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, @@ -2562,16 +2562,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) { + 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); - return (0); + 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); diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h index 65f6c10..5112476 100644 --- a/sys/fs/nfsclient/nfsnode.h +++ b/sys/fs/nfsclient/nfsnode.h @@ -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 |