From owner-dev-commits-src-all@freebsd.org Sun Mar 21 04:13:21 2021 Return-Path: Delivered-To: dev-commits-src-all@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 069945BD7DB; Sun, 21 Mar 2021 04:13: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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4F344J6jVsz3tL9; Sun, 21 Mar 2021 04:13:20 +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 D78C014659; Sun, 21 Mar 2021 04:13:20 +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 12L4DKLf085515; Sun, 21 Mar 2021 04:13:20 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12L4DKSS085514; Sun, 21 Mar 2021 04:13:20 GMT (envelope-from git) Date: Sun, 21 Mar 2021 04:13:20 GMT Message-Id: <202103210413.12L4DKSS085514@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alan Somers Subject: git: 2d1c164591ff - stable/13 - Speed up geom_stats_resync in the presence of many devices MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: asomers X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 2d1c164591ff5993cfca4b1190a345e40529593f Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Mar 2021 04:13:21 -0000 The branch stable/13 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=2d1c164591ff5993cfca4b1190a345e40529593f commit 2d1c164591ff5993cfca4b1190a345e40529593f Author: Alan Somers AuthorDate: 2021-02-27 15:59:40 +0000 Commit: Alan Somers CommitDate: 2021-03-21 02:23:42 +0000 Speed up geom_stats_resync in the presence of many devices The old code had a O(n) loop, where n is the size of /dev/devstat. Multiply that by another O(n) loop in devstat_mmap for a total of O(n^2). This change adds DIOCGMEDIASIZE support to /dev/devstat so userland can quickly determine the right amount of memory to map, eliminating the O(n) loop in userland. This change decreases the time to run "gstat -bI0.001" with 16,384 md devices from 29.7s to 4.2s. Also, fix a memory leak first reported as PR 203097. Sponsored by: Axcient Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D28968 (cherry picked from commit ab63da3564e8ab0907f9d8eb565774848ffdadeb) --- lib/libgeom/geom_stats.c | 26 +++++++++++++++++--------- sys/kern/subr_devstat.c | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/libgeom/geom_stats.c b/lib/libgeom/geom_stats.c index ebf7868c3c65..450ee491ea1c 100644 --- a/lib/libgeom/geom_stats.c +++ b/lib/libgeom/geom_stats.c @@ -32,9 +32,12 @@ */ #include +#include +#include #include #include #include +#include #include #include #include @@ -53,7 +56,7 @@ geom_stats_close(void) { if (statsfd == -1) return; - munmap(statp, npages *pagesize); + munmap(statp, npages * pagesize); statp = NULL; close (statsfd); statsfd = -1; @@ -63,17 +66,22 @@ void geom_stats_resync(void) { void *p; + off_t mediasize; + int error; if (statsfd == -1) return; - for (;;) { - p = mmap(statp, (npages + 1) * pagesize, - PROT_READ, MAP_SHARED, statsfd, 0); - if (p == MAP_FAILED) - break; - else - statp = p; - npages++; + error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize); + if (error) + err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")"); + + munmap(statp, npages * pagesize); + p = mmap(statp, mediasize, PROT_READ, MAP_SHARED, statsfd, 0); + if (p == MAP_FAILED) + err(1, "mmap(/dev/devstat):"); + else { + statp = p; + npages = mediasize / pagesize; } } diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index 091164a11fcf..98a41fd179c2 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -473,10 +474,12 @@ SYSCTL_INT(_kern_devstat, OID_AUTO, version, CTLFLAG_RD, #define statsperpage (PAGE_SIZE / sizeof(struct devstat)) +static d_ioctl_t devstat_ioctl; static d_mmap_t devstat_mmap; static struct cdevsw devstat_cdevsw = { .d_version = D_VERSION, + .d_ioctl = devstat_ioctl, .d_mmap = devstat_mmap, .d_name = "devstat", }; @@ -487,9 +490,26 @@ struct statspage { u_int nfree; }; +static size_t pagelist_pages = 0; static TAILQ_HEAD(, statspage) pagelist = TAILQ_HEAD_INITIALIZER(pagelist); static MALLOC_DEFINE(M_DEVSTAT, "devstat", "Device statistics"); +static int +devstat_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, + struct thread *td) +{ + int error = ENOTTY; + + switch (cmd) { + case DIOCGMEDIASIZE: + error = 0; + *(off_t *)data = pagelist_pages * PAGE_SIZE; + break; + } + + return (error); +} + static int devstat_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) @@ -556,6 +576,7 @@ devstat_alloc(void) * head but the order on the list determine the * sequence of the mapping so we can't do that. */ + pagelist_pages++; TAILQ_INSERT_TAIL(&pagelist, spp, list); } else break;