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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to