aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2021-03-23 20:04:37 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2021-03-23 20:04:37 +0000
commit82ee386c2afb42388804c1189751b83048953433 (patch)
tree46c6827a3ae690a15cb827c3a42f0d9b1ef979c8
parented42b22abc48ba53aaa38e1e64438b6d71e7e944 (diff)
downloadsrc-82ee386c2afb42388804c1189751b83048953433.tar.gz
src-82ee386c2afb42388804c1189751b83048953433.zip
nfsv4 client: fix forced dismount when sleeping in the renew thread
During a recent NFSv4 testing event a test server caused a hang where "umount -N" failed. The renew thread was sleeping on "nfsv4lck" and the "umount" was sleeping, waiting for the renew thread to terminate. This is the second of two patches that is hoped to fix the renew thread so that it will terminate when "umount -N" is done on the mount. This patch adds a 5second timeout on the msleep()s and checks for the forced dismount flag so that the renew thread will wake up and see the forced dismount flag. Normally a wakeup() will occur in less than 5seconds, but if a premature return from msleep() does occur, it will simply loop around and msleep() again. The patch also adds the "mp" argument to nfsv4_lock() so that it will return when the forced dismount flag is set. While here, replace the nfsmsleep() wrapper that was used for portability with the actual msleep() call. MFC after: 2 weeks
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 227d82a5f7f3..4e3abf82c96a 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -2550,10 +2550,12 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
struct nfsclrecalllayout *recallp;
struct nfsclds *dsp;
bool retok;
+ struct mount *mp;
cred = newnfs_getcred();
NFSLOCKCLSTATE();
clp->nfsc_flags |= NFSCLFLAGS_HASTHREAD;
+ mp = clp->nfsc_nmp->nm_mountp;
NFSUNLOCKCLSTATE();
for(;;) {
newnfs_setroot(cred);
@@ -2652,14 +2654,18 @@ tryagain:
}
dp->nfsdl_rwlock.nfslock_lock |=
NFSV4LOCK_WANTED;
- (void) nfsmsleep(&dp->nfsdl_rwlock,
- NFSCLSTATEMUTEXPTR, PZERO, "nfscld",
- NULL);
+ msleep(&dp->nfsdl_rwlock,
+ NFSCLSTATEMUTEXPTR, PVFS, "nfscld",
+ 5 * hz);
+ if (NFSCL_FORCEDISM(mp))
+ goto terminate;
goto tryagain;
}
while (!igotlock) {
igotlock = nfsv4_lock(&clp->nfsc_lock, 1,
- &islept, NFSCLSTATEMUTEXPTR, NULL);
+ &islept, NFSCLSTATEMUTEXPTR, mp);
+ if (igotlock == 0 && NFSCL_FORCEDISM(mp))
+ goto terminate;
if (islept)
goto tryagain;
}
@@ -2739,9 +2745,11 @@ tryagain2:
NFSV4LOCK_LOCK) != 0) {
lyp->nfsly_lock.nfslock_lock |=
NFSV4LOCK_WANTED;
- nfsmsleep(&lyp->nfsly_lock.nfslock_lock,
- NFSCLSTATEMUTEXPTR, PZERO, "nfslyp",
- NULL);
+ msleep(&lyp->nfsly_lock.nfslock_lock,
+ NFSCLSTATEMUTEXPTR, PVFS, "nfslyp",
+ 5 * hz);
+ if (NFSCL_FORCEDISM(mp))
+ goto terminate;
goto tryagain2;
}
/* Move the layout to the recall list. */
@@ -2850,6 +2858,7 @@ tryagain2:
if ((clp->nfsc_flags & NFSCLFLAGS_RECOVER) == 0)
(void)mtx_sleep(clp, NFSCLSTATEMUTEXPTR, PWAIT, "nfscl",
hz);
+terminate:
if (clp->nfsc_flags & NFSCLFLAGS_UMOUNT) {
clp->nfsc_flags &= ~NFSCLFLAGS_HASTHREAD;
NFSUNLOCKCLSTATE();