summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2017-05-08 20:21:10 +0000
committerrmacklem <rmacklem@FreeBSD.org>2017-05-08 20:21:10 +0000
commit9bc82128d57d119fc66b19a41aac9c04e3729414 (patch)
treee72d133f6fdc6f93d1a7ef88842c8143075e3c6f /sys/fs
parent572e01a8599a176db6d58cd6d621b534fd6150c5 (diff)
downloadFreeBSD-src-9bc82128d57d119fc66b19a41aac9c04e3729414.zip
FreeBSD-src-9bc82128d57d119fc66b19a41aac9c04e3729414.tar.gz
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.
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 7ae197e..f12757d 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -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(u_int32_t);
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 nfsclclient **clpp, NFSPROC_T *p)
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 nfsclclient **clpp, NFSPROC_T *p)
*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 nfsclclient **clpp, NFSPROC_T *p)
}
/* 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, uint8_t *fhp, int fhlen,
}
/*
- * 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, struct nfscllayout *lyp,
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,
OpenPOWER on IntegriCloud