Fix an NFSv4.1 client specific case where a forced dismount would hang.

The hang occurred in nfsv4_setsequence() when it couldn't find an
available session slot and is fixed by checking for a forced dismount
in progress and just returning for this case.

MFC after:	1 month
This commit is contained in:
Rick Macklem 2013-11-09 21:24:56 +00:00
parent d4e70c8074
commit 42b6336a98
3 changed files with 21 additions and 7 deletions

View File

@ -3693,8 +3693,8 @@ nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep)
* Generate the xdr for an NFSv4.1 Sequence Operation. * Generate the xdr for an NFSv4.1 Sequence Operation.
*/ */
APPLESTATIC void APPLESTATIC void
nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep, nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
int dont_replycache) struct nfsclsession *sep, int dont_replycache)
{ {
uint32_t *tl, slotseq = 0; uint32_t *tl, slotseq = 0;
int i, maxslot, slotpos; int i, maxslot, slotpos;
@ -3717,9 +3717,21 @@ nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
} }
bitval <<= 1; bitval <<= 1;
} }
if (slotpos == -1) if (slotpos == -1) {
/*
* If a forced dismount is in progress, just return.
* This RPC attempt will fail when it calls
* newnfs_request().
*/
if ((nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
!= 0) {
mtx_unlock(&sep->nfsess_mtx);
return;
}
/* Wake up once/sec, to check for a forced dismount. */
(void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx, (void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
PZERO, "nfsclseq", 0); PZERO, "nfsclseq", hz);
}
} while (slotpos == -1); } while (slotpos == -1);
/* Now, find the highest slot in use. (nfsc_slots is 64bits) */ /* Now, find the highest slot in use. (nfsc_slots is 64bits) */
bitval = 1; bitval = 1;

View File

@ -265,7 +265,8 @@ int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *, int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
struct mbuf **, uint16_t); struct mbuf **, uint16_t);
void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, struct mbuf *); void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, struct mbuf *);
void nfsv4_setsequence(struct nfsrv_descript *, struct nfsclsession *, int); void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *,
struct nfsclsession *, int);
void nfsv4_freeslot(struct nfsclsession *, int); void nfsv4_freeslot(struct nfsclsession *, int);
/* nfs_clcomsubs.c */ /* nfs_clcomsubs.c */

View File

@ -203,10 +203,11 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_SEQUENCE); *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
if (sep == NULL) if (sep == NULL)
nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp), nfsv4_setsequence(nmp, nd,
NFSMNT_MDSSESSION(nmp),
nfs_bigreply[procnum]); nfs_bigreply[procnum]);
else else
nfsv4_setsequence(nd, sep, nfsv4_setsequence(nmp, nd, sep,
nfs_bigreply[procnum]); nfs_bigreply[procnum]);
} }
if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {