nfscl: Do pNFS layout return_on_close synchronously
For pNFS servers that specify that Layouts are to be returned upon close, they may expect that LayoutReturn to happen before the associated Close. This patch modifies the NFSv4.1/4.2 pNFS client so that this is done. This only affects a pNFS mount against a non-FreeBSD NFSv4.1/4.2 server that specifies return_on_close in LayoutGet replies. Found during a recent IETF NFSv4 working group testing event. MFC after: 2 weeks
This commit is contained in:
parent
627d5d1966
commit
d5d2ce1c85
@ -273,6 +273,7 @@ struct nfscllayout {
|
||||
#define NFSLY_RETONCLOSE 0x0080
|
||||
#define NFSLY_WRITTEN 0x0100 /* Has been used to write to a DS. */
|
||||
#define NFSLY_FLEXFILE 0x0200
|
||||
#define NFSLY_RETURNED 0x0400
|
||||
|
||||
/*
|
||||
* Flex file layout mirror specific stuff for nfsclflayout.
|
||||
|
@ -127,7 +127,7 @@ static struct nfsclclient *nfscl_getclntsess(uint8_t *);
|
||||
static struct nfscldeleg *nfscl_finddeleg(struct nfsclclient *, u_int8_t *,
|
||||
int);
|
||||
static void nfscl_retoncloselayout(vnode_t, struct nfsclclient *, uint8_t *,
|
||||
int, struct nfsclrecalllayout **);
|
||||
int, struct nfsclrecalllayout **, struct nfscllayout **);
|
||||
static void nfscl_reldevinfo_locked(struct nfscldevinfo *);
|
||||
static struct nfscllayout *nfscl_findlayout(struct nfsclclient *, u_int8_t *,
|
||||
int);
|
||||
@ -2934,7 +2934,8 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
|
||||
while (lyp != NULL) {
|
||||
nlyp = TAILQ_PREV(lyp, nfscllayouthead, nfsly_list);
|
||||
if (lyp->nfsly_timestamp < NFSD_MONOSEC &&
|
||||
(lyp->nfsly_flags & NFSLY_RECALL) == 0 &&
|
||||
(lyp->nfsly_flags & (NFSLY_RECALL |
|
||||
NFSLY_RETONCLOSE)) == 0 &&
|
||||
lyp->nfsly_lock.nfslock_usecnt == 0 &&
|
||||
lyp->nfsly_lock.nfslock_lock == 0) {
|
||||
NFSCL_DEBUG(4, "ret stale lay=%d\n",
|
||||
@ -2969,7 +2970,13 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
|
||||
TAILQ_REMOVE(&rlh, lyp, nfsly_list);
|
||||
NFSCL_DEBUG(4, "ret layout\n");
|
||||
nfscl_layoutreturn(clp->nfsc_nmp, lyp, cred, p);
|
||||
nfscl_freelayout(lyp);
|
||||
if ((lyp->nfsly_flags & NFSLY_RETONCLOSE) != 0) {
|
||||
NFSLOCKCLSTATE();
|
||||
lyp->nfsly_flags |= NFSLY_RETURNED;
|
||||
wakeup(lyp);
|
||||
NFSUNLOCKCLSTATE();
|
||||
} else
|
||||
nfscl_freelayout(lyp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3334,6 +3341,7 @@ nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p)
|
||||
struct nfscldeleg *dp;
|
||||
struct nfsfh *nfhp;
|
||||
struct nfsclrecalllayout *recallp;
|
||||
struct nfscllayout *lyp;
|
||||
int error;
|
||||
|
||||
error = nfscl_getcl(vp->v_mount, NULL, NULL, false, true, &clp);
|
||||
@ -3363,7 +3371,8 @@ nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p)
|
||||
}
|
||||
|
||||
/* Return any layouts marked return on close. */
|
||||
nfscl_retoncloselayout(vp, clp, nfhp->nfh_fh, nfhp->nfh_len, &recallp);
|
||||
nfscl_retoncloselayout(vp, clp, nfhp->nfh_fh, nfhp->nfh_len, &recallp,
|
||||
&lyp);
|
||||
|
||||
/* Now process the opens against the server. */
|
||||
LIST_INIT(&delayed);
|
||||
@ -3394,6 +3403,20 @@ nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p)
|
||||
}
|
||||
}
|
||||
nfscl_clrelease(clp);
|
||||
|
||||
/* Now, wait for any layout that is returned upon close. */
|
||||
if (lyp != NULL) {
|
||||
while ((lyp->nfsly_flags & NFSLY_RETURNED) == 0) {
|
||||
if (NFSCL_FORCEDISM(nmp->nm_mountp)) {
|
||||
lyp = NULL;
|
||||
break;
|
||||
}
|
||||
msleep(lyp, NFSCLSTATEMUTEXPTR, PZERO, "nfslroc", hz);
|
||||
}
|
||||
if (lyp != NULL)
|
||||
nfscl_freelayout(lyp);
|
||||
}
|
||||
|
||||
NFSUNLOCKCLSTATE();
|
||||
/*
|
||||
* recallp has been set NULL by nfscl_retoncloselayout() if it was
|
||||
@ -5233,28 +5256,34 @@ nfscl_getlayout(struct nfsclclient *clp, uint8_t *fhp, int fhlen,
|
||||
*/
|
||||
static void
|
||||
nfscl_retoncloselayout(vnode_t vp, struct nfsclclient *clp, uint8_t *fhp,
|
||||
int fhlen, struct nfsclrecalllayout **recallpp)
|
||||
int fhlen, struct nfsclrecalllayout **recallpp, struct nfscllayout **lypp)
|
||||
{
|
||||
struct nfscllayout *lyp;
|
||||
uint32_t iomode;
|
||||
|
||||
*lypp = NULL;
|
||||
if (vp->v_type != VREG || !NFSHASPNFS(VFSTONFS(vp->v_mount)) ||
|
||||
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 |
|
||||
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, 0, 0, NULL,
|
||||
*recallpp);
|
||||
NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
|
||||
*recallpp = NULL;
|
||||
if (lyp != NULL && (lyp->nfsly_flags & NFSLY_RETONCLOSE) != 0) {
|
||||
if ((lyp->nfsly_flags & NFSLY_RECALL) == 0) {
|
||||
iomode = 0;
|
||||
if (!LIST_EMPTY(&lyp->nfsly_flayread))
|
||||
iomode |= NFSLAYOUTIOMODE_READ;
|
||||
if (!LIST_EMPTY(&lyp->nfsly_flayrw))
|
||||
iomode |= NFSLAYOUTIOMODE_RW;
|
||||
nfscl_layoutrecall(NFSLAYOUTRETURN_FILE, lyp, iomode,
|
||||
0, UINT64_MAX, lyp->nfsly_stateid.seqid, 0, 0, NULL,
|
||||
*recallpp);
|
||||
NFSCL_DEBUG(4, "retoncls recall iomode=%d\n", iomode);
|
||||
*recallpp = NULL;
|
||||
}
|
||||
|
||||
/* Now, wake up renew thread to do LayoutReturn. */
|
||||
wakeup(clp);
|
||||
*lypp = lyp;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user