summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2013-11-09 21:24:56 +0000
committerrmacklem <rmacklem@FreeBSD.org>2013-11-09 21:24:56 +0000
commit1ab8f0512b19c420fa538e3d691e86cee0b98f4d (patch)
treed75ef61ee7f8712e0b8168e1ccf150bc047d25f8 /sys/fs
parent0ab3bf57caf5ccc0b10318a3208854b6c0f7263e (diff)
downloadFreeBSD-src-1ab8f0512b19c420fa538e3d691e86cee0b98f4d.zip
FreeBSD-src-1ab8f0512b19c420fa538e3d691e86cee0b98f4d.tar.gz
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
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c20
-rw-r--r--sys/fs/nfs/nfs_var.h3
-rw-r--r--sys/fs/nfsclient/nfs_clcomsubs.c5
3 files changed, 21 insertions, 7 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index b60b0eb..0ee06bd 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -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.
*/
APPLESTATIC void
-nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
- int dont_replycache)
+nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
+ struct nfsclsession *sep, int dont_replycache)
{
uint32_t *tl, slotseq = 0;
int i, maxslot, slotpos;
@@ -3717,9 +3717,21 @@ nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
}
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,
- PZERO, "nfsclseq", 0);
+ PZERO, "nfsclseq", hz);
+ }
} while (slotpos == -1);
/* Now, find the highest slot in use. (nfsc_slots is 64bits) */
bitval = 1;
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 1edb8a3..f6a974e 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -265,7 +265,8 @@ int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
struct mbuf **, uint16_t);
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);
/* nfs_clcomsubs.c */
diff --git a/sys/fs/nfsclient/nfs_clcomsubs.c b/sys/fs/nfsclient/nfs_clcomsubs.c
index 073c6cc..52dcaad 100644
--- a/sys/fs/nfsclient/nfs_clcomsubs.c
+++ b/sys/fs/nfsclient/nfs_clcomsubs.c
@@ -203,10 +203,11 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
if (sep == NULL)
- nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp),
+ nfsv4_setsequence(nmp, nd,
+ NFSMNT_MDSSESSION(nmp),
nfs_bigreply[procnum]);
else
- nfsv4_setsequence(nd, sep,
+ nfsv4_setsequence(nmp, nd, sep,
nfs_bigreply[procnum]);
}
if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
OpenPOWER on IntegriCloud