From owner-svn-src-head@freebsd.org Tue Jan 7 04:34:04 2020 Return-Path: Delivered-To: svn-src-head@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 5C2D31FB41B; Tue, 7 Jan 2020 04:34:04 +0000 (UTC) (envelope-from mjg@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) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47sKJr1pbnz4fwS; Tue, 7 Jan 2020 04:34:04 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 39382217CD; Tue, 7 Jan 2020 04:34:04 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0074Y4Dv038450; Tue, 7 Jan 2020 04:34:04 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0074Y4Wn038449; Tue, 7 Jan 2020 04:34:04 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <202001070434.0074Y4Wn038449@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Tue, 7 Jan 2020 04:34:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r356435 - head/sys/kern X-SVN-Group: head X-SVN-Commit-Author: mjg X-SVN-Commit-Paths: head/sys/kern X-SVN-Commit-Revision: 356435 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Jan 2020 04:34:04 -0000 Author: mjg Date: Tue Jan 7 04:34:03 2020 New Revision: 356435 URL: https://svnweb.freebsd.org/changeset/base/356435 Log: vfs: prevent numvnodes and freevnodes re-reads when appropriate Otherwise in code like this: if (numvnodes > desiredvnodes) vnlru_free_locked(numvnodes - desiredvnodes, NULL); numvnodes can drop below desiredvnodes prior to the call and if the compiler generated another read the subtraction would get a negative value. Modified: head/sys/kern/vfs_subr.c Modified: head/sys/kern/vfs_subr.c ============================================================================== --- head/sys/kern/vfs_subr.c Tue Jan 7 04:33:14 2020 (r356434) +++ head/sys/kern/vfs_subr.c Tue Jan 7 04:34:03 2020 (r356435) @@ -1211,16 +1211,19 @@ vnlru_free(int count, struct vfsops *mnt_op) static int vspace(void) { + u_long rnumvnodes, rfreevnodes; int space; gapvnodes = imax(desiredvnodes - wantfreevnodes, 100); vhiwat = gapvnodes / 11; /* 9% -- just under the 10% in vlrureclaim() */ vlowat = vhiwat / 2; - if (numvnodes > desiredvnodes) + rnumvnodes = atomic_load_long(&numvnodes); + rfreevnodes = atomic_load_long(&freevnodes); + if (rnumvnodes > desiredvnodes) return (0); - space = desiredvnodes - numvnodes; + space = desiredvnodes - rnumvnodes; if (freevnodes > wantfreevnodes) - space += freevnodes - wantfreevnodes; + space += rfreevnodes - wantfreevnodes; return (space); } @@ -1292,6 +1295,7 @@ static int vnlruproc_sig; static void vnlru_proc(void) { + u_long rnumvnodes, rfreevnodes; struct mount *mp, *nmp; unsigned long onumvnodes; int done, force, trigger, usevnodes, vsp; @@ -1304,13 +1308,14 @@ vnlru_proc(void) for (;;) { kproc_suspend_check(vnlruproc); mtx_lock(&vnode_free_list_mtx); + rnumvnodes = atomic_load_long(&numvnodes); /* * If numvnodes is too large (due to desiredvnodes being * adjusted using its sysctl, or emergency growth), first * try to reduce it by discarding from the free list. */ - if (numvnodes > desiredvnodes) - vnlru_free_locked(numvnodes - desiredvnodes, NULL); + if (rnumvnodes > desiredvnodes) + vnlru_free_locked(rnumvnodes - desiredvnodes, NULL); /* * Sleep if the vnode cache is in a good state. This is * when it is not over-full and has space for about a 4% @@ -1332,7 +1337,10 @@ vnlru_proc(void) } mtx_unlock(&vnode_free_list_mtx); done = 0; - onumvnodes = numvnodes; + rnumvnodes = atomic_load_long(&numvnodes); + rfreevnodes = atomic_load_long(&freevnodes); + + onumvnodes = rnumvnodes; /* * Calculate parameters for recycling. These are the same * throughout the loop to give some semblance of fairness. @@ -1340,10 +1348,10 @@ vnlru_proc(void) * of resident pages. We aren't trying to free memory; we * are trying to recycle or at least free vnodes. */ - if (numvnodes <= desiredvnodes) - usevnodes = numvnodes - freevnodes; + if (rnumvnodes <= desiredvnodes) + usevnodes = rnumvnodes - rfreevnodes; else - usevnodes = numvnodes; + usevnodes = rnumvnodes; if (usevnodes <= 0) usevnodes = 1; /* @@ -1516,14 +1524,17 @@ getnewvnode_wait(int suspended) void getnewvnode_reserve(u_int count) { + u_long rnumvnodes, rfreevnodes; struct thread *td; /* Pre-adjust like the pre-adjust in getnewvnode(), with any count. */ /* XXX no longer so quick, but this part is not racy. */ mtx_lock(&vnode_free_list_mtx); - if (numvnodes + count > desiredvnodes && freevnodes > wantfreevnodes) - vnlru_free_locked(ulmin(numvnodes + count - desiredvnodes, - freevnodes - wantfreevnodes), NULL); + rnumvnodes = atomic_load_long(&numvnodes); + rfreevnodes = atomic_load_long(&freevnodes); + if (rnumvnodes + count > desiredvnodes && rfreevnodes > wantfreevnodes) + vnlru_free_locked(ulmin(rnumvnodes + count - desiredvnodes, + rfreevnodes - wantfreevnodes), NULL); mtx_unlock(&vnode_free_list_mtx); td = curthread;