svn commit: r317977 - stable/11/sys/fs/nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Mon May 8 20:21:12 UTC 2017
Author: rmacklem
Date: Mon May 8 20:21:10 2017
New Revision: 317977
URL: https://svnweb.freebsd.org/changeset/base/317977
Log:
MFC: r317305
Fix the NFSv4.1/pNFS client return layout on close.
The "return layout on close" case in the pNFS client was badly broken.
Fortunately, extant pNFS servers that I have tested against do not
do this. This patch fixes it. It also changes the way the layout stateid.seqid
is set for LayoutReturn. I think this change is correct w.r.t. the RFC,
but I am not 100% sure.
This was found during recent testing of the pNFS server under development.
Modified:
stable/11/sys/fs/nfsclient/nfs_clstate.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clstate.c Mon May 8 20:09:23 2017 (r317976)
+++ stable/11/sys/fs/nfsclient/nfs_clstate.c Mon May 8 20:21:10 2017 (r317977)
@@ -88,6 +88,8 @@ extern struct nfsstatsv1 nfsstatsv1;
extern struct nfsreqhead nfsd_reqq;
extern u_int32_t newnfs_false, newnfs_true;
extern int nfscl_debuglevel;
+extern int nfscl_enablecallb;
+extern int nfs_numnfscbd;
NFSREQSPINLOCK;
NFSCLSTATEMUTEX;
int nfscl_inited = 0;
@@ -118,7 +120,8 @@ static struct nfsclclient *nfscl_getclnt
static struct nfsclclient *nfscl_getclntsess(uint8_t *);
static struct nfscldeleg *nfscl_finddeleg(struct nfsclclient *, u_int8_t *,
int);
-static void nfscl_retoncloselayout(struct nfsclclient *, uint8_t *, int);
+static void nfscl_retoncloselayout(vnode_t, struct nfsclclient *, uint8_t *,
+ int, struct nfsclrecalllayout **);
static void nfscl_reldevinfo_locked(struct nfscldevinfo *);
static struct nfscllayout *nfscl_findlayout(struct nfsclclient *, u_int8_t *,
int);
@@ -3121,6 +3124,7 @@ nfscl_doclose(vnode_t vp, struct nfsclcl
struct nfsclopen *op;
struct nfscldeleg *dp;
struct nfsfh *nfhp;
+ struct nfsclrecalllayout *recallp;
int error;
error = nfscl_getcl(vnode_mount(vp), NULL, NULL, 1, &clp);
@@ -3129,6 +3133,7 @@ nfscl_doclose(vnode_t vp, struct nfsclcl
*clpp = clp;
nfhp = VTONFS(vp)->n_fhp;
+ recallp = malloc(sizeof(*recallp), M_NFSLAYRECALL, M_WAITOK);
NFSLOCKCLSTATE();
/*
* First get rid of the local Open structures, which should be no
@@ -3148,7 +3153,7 @@ nfscl_doclose(vnode_t vp, struct nfsclcl
}
/* Return any layouts marked return on close. */
- nfscl_retoncloselayout(clp, nfhp->nfh_fh, nfhp->nfh_len);
+ nfscl_retoncloselayout(vp, clp, nfhp->nfh_fh, nfhp->nfh_len, &recallp);
/* Now process the opens against the server. */
lookformore:
@@ -3171,6 +3176,11 @@ lookformore:
}
}
NFSUNLOCKCLSTATE();
+ /*
+ * recallp has been set NULL by nfscl_retoncloselayout() if it was
+ * used by the function, but calling free() with a NULL pointer is ok.
+ */
+ free(recallp, M_NFSLAYRECALL);
return (0);
}
@@ -4890,28 +4900,32 @@ nfscl_getlayout(struct nfsclclient *clp,
}
/*
- * Search for a layout by MDS file handle. If one is found that is marked
- * "return on close", delete it, since it should now be forgotten.
+ * Search for a layout by MDS file handle. If one is found, mark in to be
+ * recalled, if it already marked "return on close".
*/
static void
-nfscl_retoncloselayout(struct nfsclclient *clp, uint8_t *fhp, int fhlen)
+nfscl_retoncloselayout(vnode_t vp, struct nfsclclient *clp, uint8_t *fhp,
+ int fhlen, struct nfsclrecalllayout **recallpp)
{
struct nfscllayout *lyp;
+ uint32_t iomode;
-tryagain:
+ if (vp->v_type != VREG || !NFSHASPNFS(VFSTONFS(vnode_mount(vp))) ||
+ nfscl_enablecallb == 0 || nfs_numnfscbd == 0 ||
+ (VTONFS(vp)->n_flag & NNOLAYOUT) != 0)
+ return;
lyp = nfscl_findlayout(clp, fhp, fhlen);
- if (lyp != NULL && (lyp->nfsly_flags & NFSLY_RETONCLOSE) != 0) {
- /*
- * Wait for outstanding I/O ops to be done.
- */
- if (lyp->nfsly_lock.nfslock_usecnt != 0 ||
- lyp->nfsly_lock.nfslock_lock != 0) {
- lyp->nfsly_lock.nfslock_lock |= NFSV4LOCK_WANTED;
- (void)mtx_sleep(&lyp->nfsly_lock,
- NFSCLSTATEMUTEXPTR, PZERO, "nfslyc", 0);
- goto tryagain;
- }
- nfscl_freelayout(lyp);
+ if (lyp != NULL && (lyp->nfsly_flags & (NFSLY_RETONCLOSE |
+ NFSLY_RECALL)) == NFSLY_RETONCLOSE) {
+ iomode = 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, *recallpp);
+ NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
+ *recallpp = NULL;
}
}
@@ -5195,8 +5209,8 @@ nfscl_layoutreturn(struct nfsmount *nmp,
nfsv4stateid_t stateid;
NFSBCOPY(lyp->nfsly_stateid.other, stateid.other, NFSX_STATEIDOTHER);
+ stateid.seqid = lyp->nfsly_stateid.seqid;
LIST_FOREACH(rp, &lyp->nfsly_recall, nfsrecly_list) {
- stateid.seqid = rp->nfsrecly_stateseqid;
(void)nfsrpc_layoutreturn(nmp, lyp->nfsly_fh,
lyp->nfsly_fhlen, 0, NFSLAYOUT_NFSV4_1_FILES,
rp->nfsrecly_iomode, rp->nfsrecly_recalltype,
More information about the svn-src-stable-11
mailing list