From nobody Mon Jul 22 23:33:21 2024 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4WSc692sycz5QQWw; Mon, 22 Jul 2024 23:33:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4WSc692gCzz4tg8; Mon, 22 Jul 2024 23:33:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1721691201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=BdgEHL2oOgJ3gUk1fV4LquRBc6obB9uAcWZzV6vX6ic=; b=f1rzvY+fYq4S26wmpiGa5+UMn9RxN3sau8bD5iuIHgPza3VtlIyn7BFd/b4NukEerjxX5O IGGyYUiLXmfiEWzy2OgzZTKLFA9I8pP9yD3eHaf5U9CrY4+sqYnw3SQVQ0VpejQxcSmxzY SxTGDDPxvM7c7Sh54PqD7oVz/o/0QYvS/MdMqvjIN961+s+XKC15PQkOdYXVzEPPMjoyYQ SCmaotQquomncufGbSRQNjB1C17qAuLkLsgvvCnJJf3b0kfPVaQAya5YPM3vj+jlvQFP1F EvFWl8Bmf03hm6g30UZhnDyRMhR4+gcxxLosBLmmGooe2An6o8IuAJzhE6/QgA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1721691201; a=rsa-sha256; cv=none; b=XLv4ZAlx+xxbiEeOZtGz5onn+CgOIdWveRjIV9R1OLqSN/C7pritupYUkNBAYr3W0nF4sE y8gQYHaL3hIHWz1Cx/q14SJmAbwXhNlwEuY3HYveETLs0i/vrVhn5YGoCzVsZG4KmGhbF6 ZNza5O/+K5URSKrVNSPN6edF+qWJNK27A8qAwM7LQ0+LErw/aggsO2RuWhO8XRZzZPtwAV +yAC7MMfDc/+fpKPMDLYorOR3E43nkAswc2P1isv7KK70TgHORv4CYylAUcE2/qyCOXyOh Ss497N4I2m7PsKMMiQKNS728a9ykxLjYqmqXBS6SCx0+kKbUC7j0bNlL9/YNtQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1721691201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=BdgEHL2oOgJ3gUk1fV4LquRBc6obB9uAcWZzV6vX6ic=; b=cZ8TlirlsEFa49BbZzpELEf7wfE1NrMtkGuT+fMdpFCKQTDUoCYxDgUXdGQfo5pajmzvww xIwAi01Corjf1y8VCJC/xmvADiFtBfbX7RV7anWP1HIqSNBlw0bj+frIzlgr9m8ipWJCCi mCFNV1rRELWStOJdklQ4+BiVDAtYC9GF8Nq42zfL/F/Jsz0ZWERdB8PVAd5HmprDpArjg9 zNzzv2uQfdiJ+HBLAzy0f4C5qE3nAXru8K6nPSN0k03U/MV/+9QbSC8hwbvvLztz3jR53U DwZX9xe8FPNFQMFm1SP2jAMvzLN1CF0rjGwqphEczbiJLVxDs/8g4n8ZqIprpQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4WSc692BJtz14b3; Mon, 22 Jul 2024 23:33:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 46MNXLdI015421; Mon, 22 Jul 2024 23:33:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 46MNXLSI015418; Mon, 22 Jul 2024 23:33:21 GMT (envelope-from git) Date: Mon, 22 Jul 2024 23:33:21 GMT Message-Id: <202407222333.46MNXLSI015418@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Rick Macklem Subject: git: e6d78780c9cc - stable/13 - nfsd: Allow a mutex lock for clientID handling List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: e6d78780c9cc13f5c4f353404b54292cd060251c Auto-Submitted: auto-generated The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=e6d78780c9cc13f5c4f353404b54292cd060251c commit e6d78780c9cc13f5c4f353404b54292cd060251c Author: Rick Macklem AuthorDate: 2024-06-22 22:56:40 +0000 Commit: Rick Macklem CommitDate: 2024-07-22 22:18:16 +0000 nfsd: Allow a mutex lock for clientID handling On Feb. 28, a problem was reported on freebsd-stable@ where a nfsd thread processing an ExchangeID operation was blocked for a long time by another nfsd thread performing a copy_file_range. This occurred because the copy_file_range was taking a long time, but also because handling a clientID requires that all other nfsd threads be blocked via an exclusive lock, as required by ExchangeID. This patch allows clientID handling to be done with only a mutex held (instead of an exclusive lock that blocks all other nfsd threads) when vfs.nfsd.enable_locallocks is 0. For the case of vfs.nfsd.enable_locallocks set to 1, the exclusive lock that blocks all nfsd threads is still required. This patch does make changing the value of vfs.nfsd.enable_locallocks somewhat racy. A future commit will ensure any change is done when all nfsd threads are blocked to avoid this racyness. (cherry picked from commit dfaeeacc2cc29d0497ecd4cd5b7fd0d5ab61fcd5) --- sys/fs/nfsserver/nfs_nfsdstate.c | 241 ++++++++++++++++++++++++++------------- 1 file changed, 161 insertions(+), 80 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 911f5053bd3c..44f8aeb2a70d 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -238,6 +238,45 @@ static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf, vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p, vnode_t *tvpp); static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp); +static void nfsrv_clientlock(bool mlocked); +static void nfsrv_clientunlock(bool mlocked); + +/* + * Lock the client structure, either with the mutex or the exclusive nfsd lock. + */ +static void +nfsrv_clientlock(bool mlocked) +{ + int igotlock; + + if (mlocked) { + NFSLOCKSTATE(); + } else { + NFSLOCKV4ROOTMUTEX(); + nfsv4_relref(&nfsv4rootfs_lock); + do { + igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, + NFSV4ROOTLOCKMUTEXPTR, NULL); + } while (!igotlock); + NFSUNLOCKV4ROOTMUTEX(); + } +} + +/* + * Unlock the client structure. + */ +static void +nfsrv_clientunlock(bool mlocked) +{ + + if (mlocked) { + NFSUNLOCKSTATE(); + } else { + NFSLOCKV4ROOTMUTEX(); + nfsv4_unlock(&nfsv4rootfs_lock, 1); + NFSUNLOCKV4ROOTMUTEX(); + } +} /* * Scan the client list for a match and either return the current one, @@ -259,7 +298,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, struct sockaddr_in6 *sin6, *rin6; #endif struct nfsdsession *sep, *nsep; - int zapit = 0, gotit, hasstate = 0, igotlock; + SVCXPRT *old_xprt; + struct nfssessionhead old_sess; + int zapit = 0, gotit, hasstate = 0; + bool mlocked; static u_int64_t confirm_index = 0; /* @@ -287,14 +329,11 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, */ new_clp->lc_program = 0; + mlocked = true; + if (nfsrv_dolocallocks != 0) + mlocked = false; /* Lock out other nfsd threads */ - NFSLOCKV4ROOTMUTEX(); - nfsv4_relref(&nfsv4rootfs_lock); - do { - igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, - NFSV4ROOTLOCKMUTEXPTR, NULL); - } while (!igotlock); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientlock(mlocked); /* * Search for a match in the client list. @@ -311,6 +350,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, if (gotit == 0) i++; } + old_xprt = NULL; if (!gotit || (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) { if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) { @@ -318,9 +358,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, * For NFSv4.1, if confirmp->lval[1] is non-zero, the * client is trying to update a confirmed clientid. */ - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); confirmp->lval[1] = 0; error = NFSERR_NOENT; goto out; @@ -330,7 +368,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, */ if (i != nfsrv_clienthashsize) { LIST_REMOVE(clp, lc_hash); - nfsrv_cleanclient(clp, p, false, NULL); + if (mlocked) + nfsrv_cleanclient(clp, p, true, &old_xprt); + else + nfsrv_cleanclient(clp, p, false, NULL); nfsrv_freedeleglist(&clp->lc_deleg); nfsrv_freedeleglist(&clp->lc_olddeleg); zapit = 1; @@ -365,11 +406,12 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, NFSD_VNET(nfsstatsv1_p)->srvclients++; nfsrv_openpluslock++; nfsrv_clients++; - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); - if (zapit) + nfsrv_clientunlock(mlocked); + if (zapit != 0) { + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); nfsrv_zapclient(clp, p); + } *new_clpp = NULL; goto out; } @@ -383,7 +425,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, */ if (clp->lc_expiry < NFSD_MONOSEC && (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) { - nfsrv_cleanclient(clp, p, false, NULL); + if (mlocked) + nfsrv_cleanclient(clp, p, true, &old_xprt); + else + nfsrv_cleanclient(clp, p, false, NULL); nfsrv_freedeleglist(&clp->lc_deleg); } @@ -428,9 +473,9 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, break; #endif } - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); error = NFSERR_CLIDINUSE; goto out; } @@ -444,13 +489,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, */ LIST_REMOVE(clp, lc_hash); - /* Get rid of all sessions on this clientid. */ - LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) { - ret = nfsrv_freesession(sep, NULL, false, NULL); - if (ret != 0) - printf("nfsrv_setclient: verifier changed free" - " session failed=%d\n", ret); - } + LIST_NEWHEAD(&old_sess, &clp->lc_session, sess_list); new_clp->lc_flags |= LCL_NEEDSCONFIRM; if ((nd->nd_flag & ND_NFSV41) != 0) { @@ -494,21 +533,31 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, NFSD_VNET(nfsstatsv1_p)->srvclients++; nfsrv_openpluslock++; nfsrv_clients++; - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + if (!mlocked) { + nfsrv_clientunlock(mlocked); + NFSLOCKSTATE(); + } /* * Must wait until any outstanding callback on the old clp * completes. */ - NFSLOCKSTATE(); while (clp->lc_cbref) { clp->lc_flags |= LCL_WAKEUPWANTED; (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, "nfsd clp", 10 * hz); } NFSUNLOCKSTATE(); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); + /* Get rid of all sessions on this clientid. */ + LIST_FOREACH_SAFE(sep, &old_sess, sess_list, nsep) { + ret = nfsrv_freesession(sep, NULL, false, NULL); + if (ret != 0) + printf("nfsrv_setclient: verifier changed free" + " session failed=%d\n", ret); + } + nfsrv_zapclient(clp, p); *new_clpp = NULL; goto out; @@ -560,24 +609,31 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, nfsrv_openpluslock++; nfsrv_clients++; } - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + if (!mlocked) + nfsrv_clientunlock(mlocked); if ((nd->nd_flag & ND_NFSV41) == 0) { /* * Must wait until any outstanding callback on the old clp * completes. */ - NFSLOCKSTATE(); + if (!mlocked) + NFSLOCKSTATE(); while (clp->lc_cbref) { clp->lc_flags |= LCL_WAKEUPWANTED; (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, "nfsdclp", 10 * hz); } NFSUNLOCKSTATE(); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); nfsrv_zapclient(clp, p); *new_clpp = NULL; + } else { + if (mlocked) + NFSUNLOCKSTATE(); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); } out: @@ -597,11 +653,13 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, struct nfsstate *stp; int i; struct nfsclienthashhead *hp; - int error = 0, igotlock, doneok; + int error = 0, doneok, igotlock; struct nfssessionhash *shp; struct nfsdsession *sep; uint64_t sessid[2]; - bool sess_replay; + CLIENT *client; + SVCXPRT *old_xprt; + bool mlocked, sess_replay; static uint64_t next_sess = 0; if (clpp) @@ -618,13 +676,27 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, * already held. Otherwise, we need to get either that or, * for the case of Confirm, lock out the nfsd threads. */ + client = NULL; + old_xprt = NULL; + mlocked = true; + if (nfsrv_dolocallocks != 0) + mlocked = false; if (opflags & CLOPS_CONFIRM) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_relref(&nfsv4rootfs_lock); - do { - igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, - NFSV4ROOTLOCKMUTEXPTR, NULL); - } while (!igotlock); + if (nsep != NULL && + (nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) + client = (struct __rpc_client *) + clnt_bck_create(nd->nd_xprt->xp_socket, + cbprogram, NFSV4_CBVERS); + if (mlocked) { + nfsrv_clientlock(mlocked); + } else { + NFSLOCKV4ROOTMUTEX(); + nfsv4_relref(&nfsv4rootfs_lock); + do { + igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, + NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); + } while (!igotlock); + } /* * Create a new sessionid here, since we need to do it where * there is a mutex held to serialize update of next_sess. @@ -633,7 +705,8 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, sessid[0] = ++next_sess; sessid[1] = clientid.qval; } - NFSUNLOCKV4ROOTMUTEX(); + if (!mlocked) + NFSUNLOCKV4ROOTMUTEX(); } else if (opflags != CLOPS_RENEW) { NFSLOCKSTATE(); } @@ -670,9 +743,9 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, } if (error) { if (opflags & CLOPS_CONFIRM) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); + if (client != NULL) + CLNT_RELEASE(client); } else if (opflags != CLOPS_RENEW) { NFSUNLOCKSTATE(); } @@ -716,7 +789,10 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, * for an Open with CLAIM_DELEGATE_PREV unless in * grace, but get rid of the rest of the state. */ - nfsrv_cleanclient(clp, p, false, NULL); + if (mlocked) + nfsrv_cleanclient(clp, p, true, &old_xprt); + else + nfsrv_cleanclient(clp, p, false, NULL); nfsrv_freedeleglist(&clp->lc_olddeleg); if (nfsrv_checkgrace(nd, clp, 0)) { /* In grace, so just delete delegations */ @@ -740,10 +816,10 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, /* Hold a reference on the xprt for a backchannel. */ if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 && !sess_replay) { - if (clp->lc_req.nr_client == NULL) - clp->lc_req.nr_client = (struct __rpc_client *) - clnt_bck_create(nd->nd_xprt->xp_socket, - cbprogram, NFSV4_CBVERS); + if (clp->lc_req.nr_client == NULL) { + clp->lc_req.nr_client = client; + client = NULL; + } if (clp->lc_req.nr_client != NULL) { SVC_ACQUIRE(nd->nd_xprt); CLNT_ACQUIRE(clp->lc_req.nr_client); @@ -760,13 +836,15 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, NFSX_V4SESSIONID); if (!sess_replay) { shp = NFSSESSIONHASH(nsep->sess_sessionid); - NFSLOCKSTATE(); + if (!mlocked) + NFSLOCKSTATE(); NFSLOCKSESSION(shp); LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); nsep->sess_clp = clp; NFSUNLOCKSESSION(shp); - NFSUNLOCKSTATE(); + if (!mlocked) + NFSUNLOCKSTATE(); } } } @@ -800,9 +878,11 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, clp->lc_expiry = nfsrv_leaseexpiry(); } if (opflags & CLOPS_CONFIRM) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); + if (client != NULL) + CLNT_RELEASE(client); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); } else if (opflags != CLOPS_RENEW) { NFSUNLOCKSTATE(); } @@ -822,21 +902,20 @@ nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) { struct nfsclient *clp; struct nfsclienthashhead *hp; - int error = 0, i, igotlock; + SVCXPRT *old_xprt; + int error = 0, i; + bool mlocked; if (NFSD_VNET(nfsrvboottime) != clientid.lval[0]) { error = NFSERR_STALECLIENTID; goto out; } + mlocked = true; + if (nfsrv_dolocallocks != 0) + mlocked = false; /* Lock out other nfsd threads */ - NFSLOCKV4ROOTMUTEX(); - nfsv4_relref(&nfsv4rootfs_lock); - do { - igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, - NFSV4ROOTLOCKMUTEXPTR, NULL); - } while (igotlock == 0); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientlock(mlocked); hp = NFSCLIENTHASH(clientid); LIST_FOREACH(clp, hp, lc_hash) { @@ -844,9 +923,7 @@ nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) break; } if (clp == NULL) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); /* Just return ok, since it is gone. */ goto out; } @@ -860,28 +937,28 @@ nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) /* Scan for state on the clientid. */ for (i = 0; i < nfsrv_statehashsize; i++) if (!LIST_EMPTY(&clp->lc_stateid[i])) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); error = NFSERR_CLIENTIDBUSY; goto out; } if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) { - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); error = NFSERR_CLIENTIDBUSY; goto out; } /* Destroy the clientid and return ok. */ - nfsrv_cleanclient(clp, p, false, NULL); + old_xprt = NULL; + if (mlocked) + nfsrv_cleanclient(clp, p, true, &old_xprt); + else + nfsrv_cleanclient(clp, p, false, NULL); nfsrv_freedeleglist(&clp->lc_deleg); nfsrv_freedeleglist(&clp->lc_olddeleg); LIST_REMOVE(clp, lc_hash); - NFSLOCKV4ROOTMUTEX(); - nfsv4_unlock(&nfsv4rootfs_lock, 1); - NFSUNLOCKV4ROOTMUTEX(); + nfsrv_clientunlock(mlocked); + if (old_xprt != NULL) + SVC_RELEASE(old_xprt); nfsrv_zapclient(clp, p); out: NFSEXITCODE2(error, nd); @@ -1370,8 +1447,12 @@ nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p, bool locked, struct nfsstate *stp, *nstp; struct nfsdsession *sep, *nsep; - LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) - nfsrv_freeopenowner(stp, 1, p); + LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { + if (locked) + nfsrv_freeopenowner(stp, 0, p); + else + nfsrv_freeopenowner(stp, 1, p); + } if ((clp->lc_flags & LCL_ADMINREVOKED) == 0) LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) (void)nfsrv_freesession(sep, NULL, locked, old_xprtp);