From owner-dev-commits-src-branches@freebsd.org Sat Jun 5 01:19:57 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A8C5A63868D; Sat, 5 Jun 2021 01:19:57 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Fxhd94KFKz3j0X; Sat, 5 Jun 2021 01:19:57 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 6AA1B2767C; Sat, 5 Jun 2021 01:19:57 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1551JvRd091401; Sat, 5 Jun 2021 01:19:57 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1551JvXv091400; Sat, 5 Jun 2021 01:19:57 GMT (envelope-from git) Date: Sat, 5 Jun 2021 01:19:57 GMT Message-Id: <202106050119.1551JvXv091400@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: 4fee353bcb45 - stable/13 - nfscl: Add hash lists for the NFSv4 opens 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: 4fee353bcb452022ae8a049eca7b32ab4b816b90 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Jun 2021 01:19:57 -0000 The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=4fee353bcb452022ae8a049eca7b32ab4b816b90 commit 4fee353bcb452022ae8a049eca7b32ab4b816b90 Author: Rick Macklem AuthorDate: 2021-05-22 21:51:38 +0000 Commit: Rick Macklem CommitDate: 2021-06-05 01:16:10 +0000 nfscl: Add hash lists for the NFSv4 opens A problem was reported via email, where a large (130000+) accumulation of NFSv4 opens on an NFSv4 mount caused significant lock contention on the mutex used to protect the client mount's open/lock state. Although the root cause for the accumulation of opens was not resolved, it is obvious that the NFSv4 client is not designed to handle 100000+ opens efficiently. When searching for an open, usually for a match by file handle, a linear search of all opens is done. This patch adds a table of hash lists for the opens, hashed on file handle. This table will be used by future commits to search for an open based on file handle more efficiently. (cherry picked from commit 3f7e14ad93454476bb11b4b8de5b41930d13312e) --- sys/fs/nfs/nfsclstate.h | 7 +++++++ sys/fs/nfsclient/nfs_clstate.c | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/sys/fs/nfs/nfsclstate.h b/sys/fs/nfs/nfsclstate.h index e17be74c5581..898a7de391dc 100644 --- a/sys/fs/nfs/nfsclstate.h +++ b/sys/fs/nfs/nfsclstate.h @@ -42,6 +42,7 @@ LIST_HEAD(nfsclhead, nfsclclient); LIST_HEAD(nfsclownerhead, nfsclowner); TAILQ_HEAD(nfscldeleghead, nfscldeleg); LIST_HEAD(nfscldeleghash, nfscldeleg); +LIST_HEAD(nfsclopenhash, nfsclopen); TAILQ_HEAD(nfscllayouthead, nfscllayout); LIST_HEAD(nfscllayouthash, nfscllayout); LIST_HEAD(nfsclflayouthead, nfsclflayout); @@ -50,6 +51,10 @@ LIST_HEAD(nfsclrecalllayouthead, nfsclrecalllayout); #define NFSCLDELEGHASHSIZE 256 #define NFSCLDELEGHASH(c, f, l) \ (&((c)->nfsc_deleghash[ncl_hash((f), (l)) % NFSCLDELEGHASHSIZE])) +#define NFSCLOPENHASHSIZE 256 +#define NFSCLOPENHASHFUNC(f, l) (ncl_hash((f), (l)) % NFSCLOPENHASHSIZE) +#define NFSCLOPENHASH(c, f, l) \ + (&((c)->nfsc_openhash[NFSCLOPENHASHFUNC((f), (l))])) #define NFSCLLAYOUTHASHSIZE 256 #define NFSCLLAYOUTHASH(c, f, l) \ (&((c)->nfsc_layouthash[ncl_hash((f), (l)) % NFSCLLAYOUTHASHSIZE])) @@ -104,6 +109,7 @@ struct nfsclclient { struct nfsclownerhead nfsc_owner; struct nfscldeleghead nfsc_deleg; struct nfscldeleghash nfsc_deleghash[NFSCLDELEGHASHSIZE]; + struct nfsclopenhash nfsc_openhash[NFSCLOPENHASHSIZE]; struct nfscllayouthead nfsc_layout; struct nfscllayouthash nfsc_layouthash[NFSCLLAYOUTHASHSIZE]; struct nfscldevinfohead nfsc_devinfo; @@ -183,6 +189,7 @@ struct nfscldeleg { */ struct nfsclopen { LIST_ENTRY(nfsclopen) nfso_list; + LIST_ENTRY(nfsclopen) nfso_hash; struct nfscllockownerhead nfso_lock; nfsv4stateid_t nfso_stateid; struct nfsclowner *nfso_own; diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 1ed3630ce6e7..a8eace2ffd0b 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -240,9 +240,11 @@ nfscl_open(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t amode, int usedeleg, */ nowp = malloc(sizeof (struct nfsclowner), M_NFSCLOWNER, M_WAITOK); - if (nfhp != NULL) + if (nfhp != NULL) { nop = malloc(sizeof (struct nfsclopen) + fhlen - 1, M_NFSCLOPEN, M_WAITOK); + nop->nfso_hash.le_prev = NULL; + } ret = nfscl_getcl(vp->v_mount, cred, p, 1, &clp); if (ret != 0) { free(nowp, M_NFSCLOWNER); @@ -412,6 +414,8 @@ nfscl_newopen(struct nfsclclient *clp, struct nfscldeleg *dp, dp->nfsdl_timestamp = NFSD_MONOSEC + 120; nfsstatsv1.cllocalopens++; } else { + LIST_INSERT_HEAD(NFSCLOPENHASH(clp, fhp, fhlen), + nop, nfso_hash); nfsstatsv1.clopens++; } LIST_INSERT_HEAD(&owp->nfsow_open, nop, nfso_list); @@ -837,6 +841,8 @@ nfscl_getcl(struct mount *mp, struct ucred *cred, NFSPROC_T *p, LIST_INIT(&clp->nfsc_devinfo); for (i = 0; i < NFSCLDELEGHASHSIZE; i++) LIST_INIT(&clp->nfsc_deleghash[i]); + for (i = 0; i < NFSCLOPENHASHSIZE; i++) + LIST_INIT(&clp->nfsc_openhash[i]); for (i = 0; i < NFSCLLAYOUTHASHSIZE; i++) LIST_INIT(&clp->nfsc_layouthash[i]); clp->nfsc_flags = NFSCLFLAGS_INITED; @@ -1475,6 +1481,8 @@ nfscl_freeopen(struct nfsclopen *op, int local) { LIST_REMOVE(op, nfso_list); + if (op->nfso_hash.le_prev != NULL) + LIST_REMOVE(op, nfso_hash); nfscl_freealllocks(&op->nfso_lock, local); free(op, M_NFSCLOPEN); if (local) @@ -1706,6 +1714,8 @@ nfscl_expireclient(struct nfsclclient *clp, struct nfsmount *nmp, LIST_REMOVE(op, nfso_list); op->nfso_own = towp; LIST_INSERT_HEAD(&towp->nfsow_open, op, nfso_list); + LIST_INSERT_HEAD(NFSCLOPENHASH(clp, op->nfso_fh, + op->nfso_fhlen), op, nfso_hash); nfsstatsv1.cllocalopens--; nfsstatsv1.clopens++; } @@ -1714,6 +1724,8 @@ nfscl_expireclient(struct nfsclclient *clp, struct nfsmount *nmp, LIST_REMOVE(owp, nfsow_list); owp->nfsow_clp = clp; LIST_INSERT_HEAD(&clp->nfsc_owner, owp, nfsow_list); + LIST_INSERT_HEAD(NFSCLOPENHASH(clp, op->nfso_fh, + op->nfso_fhlen), op, nfso_hash); nfsstatsv1.cllocalopenowners--; nfsstatsv1.clopenowners++; nfsstatsv1.cllocalopens--; @@ -4198,6 +4210,7 @@ nfscl_moveopen(vnode_t vp, struct nfsclclient *clp, struct nfsmount *nmp, np = VTONFS(vp); nop = malloc(sizeof (struct nfsclopen) + lop->nfso_fhlen - 1, M_NFSCLOPEN, M_WAITOK); + nop->nfso_hash.le_prev = NULL; newone = 0; nfscl_newopen(clp, NULL, &owp, NULL, &op, &nop, owp->nfsow_owner, lop->nfso_fh, lop->nfso_fhlen, cred, &newone);