Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Jun 2012 19:14:09 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Sergey Kandaurov <pluknet@FreeBSD.org>
Cc:        svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org, Eitan Adler <eadler@FreeBSD.org>
Subject:   Re: svn commit: r236380 - head/sys/vm
Message-ID:  <20120601175403.H1865@besplex.bde.org>
In-Reply-To: <CAE-mSOK=qyKbTwnKx_y5VmDNdYJG_K7R4j6565hWy09gEu_wZQ@mail.gmail.com>
References:  <201206010442.q514gqqv084148@svn.freebsd.org> <CAE-mSOK=qyKbTwnKx_y5VmDNdYJG_K7R4j6565hWy09gEu_wZQ@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--0-1047696930-1338542049=:1865
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

On Fri, 1 Jun 2012, Sergey Kandaurov wrote:

> On 1 June 2012 08:42, Eitan Adler <eadler@freebsd.org> wrote:
>> ...
>> Log:
>> =A0Add sysctl to query amount of swap space free
>>
>> =A0PR: =A0 =A0 =A0 =A0 =A0 kern/166780
>> =A0Submitted by: Radim Kolar <hsn@sendmail.cz>
>> =A0Approved by: =A0cperciva
>> =A0MFC after: =A0 =A01 week
>
> Well, we already have more powerful vm.swap_info, so
> I see no reason to add yet another one to do the same thing
> (but now with a human interface).

The new interface provides many more bugs.  Mostly style bugs, but
also type mismatches and potential overflow.

> Probably sysctl(8) should be enhanced to parse it instead.

That would be another bug.  sysctl(8) already does too much parsing.
Parsing belongs in specialized utilities, and I think there are already
some that do it for swap.  sysctl(8) largest existing exessive parsing
and presenting is for related vmtotal things.

>> Modified:
>> =A0head/sys/vm/swap_pager.c
>>
>> Modified: head/sys/vm/swap_pager.c
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> --- head/sys/vm/swap_pager.c =A0 =A0Fri Jun =A01 04:34:49 2012 =A0 =A0 =
=A0 =A0(r236379)
>> +++ head/sys/vm/swap_pager.c =A0 =A0Fri Jun =A01 04:42:52 2012 =A0 =A0 =
=A0 =A0(r236380)
>> @@ -2692,3 +2692,18 @@ swaponvp(struct thread *td, struct vnode
>> =A0 =A0 =A0 =A0 =A0 =A0NODEV);
>> =A0 =A0 =A0 =A0return (0);
>> =A0}

Please don't put binary characters in mail.

>> +
>> +static int
>> +sysctl_vm_swap_free(SYSCTL_HANDLER_ARGS) {

First style bug: misplaced brace.

>> + =A0 =A0 =A0 int swap_free, used;
>> + =A0 =A0 =A0 int total;

Second and third style bugs: int variables not altogther, and not sorted.
But these are probably actually type and overflow errors (bugs 4 and 5)...

>> +
>> + =A0 =A0 =A0 swap_pager_status(&total, &used);
>> +

Bug 6 is a style bug (extra blank line).

>> + =A0 =A0 =A0 swap_free =3D (total - used) * PAGE_SIZE;

We multiply by PAGE_SIZE.  This can probably overflow at 2G.  Then
assigning to the int variable overflows at the same point.  This gives
bugs 4 and 5.  Related sysctls for memory sizes (see kern_mib.c) avoid
this problem by using u_long instead of int.  But for disk sizes, using
u_long only reduces the problem to overflow at 4G, since systems with
32-bit longs can have larger disks than memory, and large disks can
have large swap.

I'm not sure if old restrictions on swap size have been fixed so that
more than 2G can actually be allocated, but most places that muliply
by PAGE_SIZE aee now careful to use expressions like
'(vm_ooffset_t)nblks * PAGE_SIZE' and to assign the result to a variable
of type vm_ooffset_t.  swap_total is one such variable.  But its sysctl
has type errors too.  vm_ooffset_t is just not a supported type in sysctl.
SYSCTL_QUAD() is used for it.  Quads shouldn't exist, and SYSCTL_QUAD()
should never be used, especially for non-quads.  There are now some
support for 64-bit types in sysctl.  Using these would be less bogus.

Bug 7 is a style bug: the related sysctls for memory sizes use ctob()
instead of hard-coding PAGE_SIZE.  Avoiding this style bug also avoids
multiplication overflow (else you need a cast to go above 2G starting
with an int page count).  ctob() is bogus too (seen any clicks lately?).

>> + =A0 =A0 =A0 return SYSCTL_OUT(req, &swap_free, sizeof(swap_free));

Bug 8 is a style bug (no spaces around return value).

>> +}
>> +
>> +SYSCTL_OID(_vm, OID_AUTO, swap_free, CTLTYPE_INT|CTLFLAG_RD|CTLFLAG_MPS=
AFE,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 NULL, 0, sysctl_vm_swap_free, "Q",
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 "Blocks of free swap storage.");

Bug 9 is a style bug.  I didn't even know that the raw SYSCTL_OID() could
be misused like this.  The normal SYSCTL_PROC() is identical with
SYSCTL_OID() except it checks that the access flags are not 0.  Few or no
SYSCTL_FOO()s have no access flags, and this is not one.  It has rather
excessive access flags (I think CTLFLAG_MPSAFE is unnecessary.  It is not
used for the related memory sysctls).  vm has 4 existing SYSCTL_OID()s;
kern has 3; ia64/ia64 has 1; i386/i386 has 1; netipsec has 1.  These are
the only matches for ^SYSCTL_OID in /sys, and they all seem to be just
style bugs.

Bug 10 is a collection of style bugs (missing spaces around binary operator
'|').

Bug 11 is a collection of style bugs (weird 2-tab continuation indentation
instead of the normal 4 spaces.  5 out of 7 existing SYSCTL_*()s in this
file including the vm_swap ones use normal continuation indentation.

Bug 12 is the most serious type error.  The format is "Q", but only
an int is returned.  I don't see how this can result in anything except
garbage printing in sysctl(8).  The access flag gives the type correctly
as int, but sysctl(8) mostly uses the format string for output.  Oops,
that was in an old version.  sysctl(8) now mostly uses the access flag,
and has no literal Q's in it any more.  So this error might not be
serious, depending on whether the bad format string is actually used.

The sysctl data doesn't give the size of type type, but leaves it as
0.  This works because the size is given as sizeof(swap_free) in the
call to SYSCTL_OUT().  This can be confusing, and use of the raw
SYSCTL_OUT() should be avoided if possible.  Many SYSCTL_PROC() routines
and of course all macros like SYSCTL_INT() use sysctl_handle_foo() to
handle integers.  For this, the size is unfortunately encoded in the
name of the function (so the function must be matched to the actual
type in callers) and and is hard-coded in sysctl_handle_foo().  But
unlike the raw SYSCTL_OUT(), sysctl_handle_foo() can in theory check
for consistency between its name and the types in the data and thus
detect type errors like the "Q" in the above.

Bug 13 is a style bug (termination of the sysctl description with a ".").

Bruce
--0-1047696930-1338542049=:1865--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120601175403.H1865>