From owner-svn-src-all@freebsd.org Fri Apr 21 14:22:31 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4EB5DD48724; Fri, 21 Apr 2017 14:22:31 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail110.syd.optusnet.com.au (mail110.syd.optusnet.com.au [211.29.132.97]) by mx1.freebsd.org (Postfix) with ESMTP id CE5488E1; Fri, 21 Apr 2017 14:22:30 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from besplex.bde.org (c122-106-153-191.carlnfd1.nsw.optusnet.com.au [122.106.153.191]) by mail110.syd.optusnet.com.au (Postfix) with ESMTPS id 2004C10C774; Sat, 22 Apr 2017 00:22:28 +1000 (AEST) Date: Sat, 22 Apr 2017 00:22:27 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Bruce Evans cc: Jung-uk Kim , src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r317231 - head/usr.bin/systat In-Reply-To: <20170421131652.P966@besplex.bde.org> Message-ID: <20170421232411.H2704@besplex.bde.org> References: <201704202230.v3KMUdAm030762@repo.freebsd.org> <20170421131652.P966@besplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.2 cv=AYLBJzfG c=1 sm=1 tr=0 a=Tj3pCpwHnMupdyZSltBt7Q==:117 a=Tj3pCpwHnMupdyZSltBt7Q==:17 a=kj9zAlcOel0A:10 a=j1YcvcGwAk2caA5GzGUA:9 a=CjuIK1q_8ugA:10 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Apr 2017 14:22:31 -0000 On Fri, 21 Apr 2017, Bruce Evans wrote: > On Thu, 20 Apr 2017, Jung-uk Kim wrote: > >> Log: >> Fix systat(1) regression. It was broken by r317061. > > It is more broken than before. Now it fails when the kernel is older > than the utility instead of vice versa. When it fails, the failures > are more serious than before. systat -v actually does complete > checking for errors (some are only errors in itself), but mishandles > them. It reports the errors on the status line and continues. The > error message overwrites the previous one. Continuing is more broken > than before: The follow patch reduces the ABI breakage as much as possible. On a lightly loaded system, the maximum value in any counter used by top, vmstat or systat -v is growing at a rate of 1M per hour, so the 32-bit variables in the application are enough for about 166 days. I only applied the fix to some counter sysctls with broken ABIs, but wrote it for general use. It doesn't handle SYSCTL_IN(), and assumes unsigned counters. X Index: subr_counter.c X =================================================================== X --- subr_counter.c (revision 317243) X +++ subr_counter.c (working copy) X @@ -74,6 +75,95 @@ X uma_zfree(pcpu_zone_64, c); X } X X +/* Output a signed integer with the caller's size as well as possible. */ X +__unused X +static int X +sysctl_out_i(struct sysctl_req *req, intmax_t val) X +{ X + intmax_t valtrunc; X + int64_t val64; X + int32_t val32; X + int16_t val16; X + int8_t val8; X + int error; X + X + switch (req->oldlen) { X + case 1: X + valtrunc = val8 = val; X + error = SYSCTL_OUT(req, &val8, 1); X + break; X + case 2: X + valtrunc = val16 = val; X + error = SYSCTL_OUT(req, &val16, 2); X + break; X + case 4: X + valtrunc = val32 = val; X + error = SYSCTL_OUT(req, &val32, 4); X + break; X + case 8: X + valtrunc = val64 = val; X + error = SYSCTL_OUT(req, &val64, 8); X + break; X + default: X + valtrunc = val; X + error = SYSCTL_OUT(req, &val, sizeof(val)); X + break; X + } X + if (valtrunc != val && error == 0) X + error = EOVERFLOW; X + return (error); X +} X + X +uintmax_t sysoui_max; X + X +/* Output an unsigned integer with the caller's size as well as possible. */ X +static int X +sysctl_out_ui(struct sysctl_req *req, uintmax_t val) X +{ X + uintmax_t valtrunc; X + uint64_t val64; X + uint32_t val32; X + uint16_t val16; X + uint8_t val8; X + int error; X + X + if (sysoui_max < val) { X + sysoui_max = val; X + if ((val & 0xffff) == 0) X + printf("new sysoui_max %#jx\n", val); X + } X + val64 = val32 = val16 = val8 = 0; X + switch (req->oldlen) { X + case 1: X + valtrunc = val8 = val; X + error = SYSCTL_OUT(req, &val8, 1); X + break; X + case 2: X + valtrunc = val16 = val; X + error = SYSCTL_OUT(req, &val16, 2); X + break; X + case 4: X + valtrunc = val32 = val; X + error = SYSCTL_OUT(req, &val32, 4); X + break; X + case 8: X + valtrunc = val64 = val; X + error = SYSCTL_OUT(req, &val64, 8); X + break; X + default: X + valtrunc = val; X + error = SYSCTL_OUT(req, &val, sizeof(val)); X + break; X + } X + if (valtrunc != val && error == 0) { X + printf( X + "val %#jx, valtrunc %#jx, val64 %#jx, val32 %#x, val16 %#x, val8 %#x\n", X + val, valtrunc, val64, val32, val16, val8); X + error = EOVERFLOW; X + } X + return (error); X +} X + X int X sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS) X { X @@ -82,7 +172,7 @@ X X out = counter_u64_fetch(*(counter_u64_t *)arg1); X X - error = SYSCTL_OUT(req, &out, sizeof(uint64_t)); X + error = sysctl_out_ui(req, out); X X if (error || !req->newptr) X return (error); Bruce