Discussion:
sysctl output formatting
Chris Torek
2015-04-06 22:29:22 UTC
Permalink
We had a side discussion at $work about a private sysctl emulation
(so our side thing doesn't actually affect sysctl itself at all)
where it was suggested that some simple numeric sysctls are "best
displayed in hex".

Consider, e.g.:

$ sysctl kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 65535
kern.timecounter.tc.i8254.counter: 25822
kern.timecounter.tc.i8254.frequency: 1193182
kern.timecounter.tc.i8254.quality: 0

The "mask" here actually makes more sense displayed in hex. One
can of course use:

$ sysctl -x kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 0x0000ffff
kern.timecounter.tc.i8254.counter: 0x0000786c
kern.timecounter.tc.i8254.frequency: 0x00000000001234de
kern.timecounter.tc.i8254.quality: 0000000000

but now the mask is shown in hex (yay) but the others are shown
in hex too (boo).

The suggestion made (note that I'm carefully filing off names via
passive voice :-) ) is that there could be a sysctl flag:

#define CTLFLAG_DEFHEX 0x00000800

that says that, without any additional formatting directive, the
user-level "sysctl" command should output this particular value in
hex. Obviously this eats up another flag bit (but there are a few
left) and might require a new argument to the sysctl command
("force output to be decimal", for compatibility or whatever).

Then someone said "but what about suggesting that the output be in
octal, or binary, or ..." in which case this would have to be a
bit-field rather than a single bit (a la the CTLMASK_SECURE
field).

Anyway, I volunteered to send in the idea to be bikeshedded :-)
here. It does seem like a reasonable special case to add, though
I admit it buys much more with certain huge 64-bit byte-grouped
values we have (0x0303030103030300 reads so much nicer than
217020509924295424 for instance).

If people like the idea, I could code it up as well.

Chris
Luigi Rizzo
2015-04-06 23:07:07 UTC
Permalink
Post by Chris Torek
We had a side discussion at $work about a private sysctl emulation
(so our side thing doesn't actually affect sysctl itself at all)
where it was suggested that some simple numeric sysctls are "best
displayed in hex".
$ sysctl kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 65535
kern.timecounter.tc.i8254.counter: 25822
kern.timecounter.tc.i8254.frequency: 1193182
kern.timecounter.tc.i8254.quality: 0
The "mask" here actually makes more sense displayed in hex. One
$ sysctl -x kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 0x0000ffff
kern.timecounter.tc.i8254.counter: 0x0000786c
kern.timecounter.tc.i8254.frequency: 0x00000000001234de
kern.timecounter.tc.i8254.quality: 0000000000
but now the mask is shown in hex (yay) but the others are shown
in hex too (boo).
The suggestion made (note that I'm carefully filing off names via
#define CTLFLAG_DEFHEX 0x00000800
that says that, without any additional formatting directive, the
user-level "sysctl" command should output this particular value in
hex. Obviously this eats up another flag bit (but there are a few
left) and might require a new argument to the sysctl command
("force output to be decimal", for compatibility or whatever).
Then someone said "but what about suggesting that the output be in
octal, or binary, or ..." in which case this would have to be a
bit-field rather than a single bit (a la the CTLMASK_SECURE
field).
Anyway, I volunteered to send in the idea to be bikeshedded :-)
here. It does seem like a reasonable special case to add, though
I admit it buys much more with certain huge 64-bit byte-grouped
values we have (0x0303030103030300 reads so much nicer than
217020509924295424 for instance).
since we are in bikeshed territory how about instead
(or in addition) building a small wrapper/sysctl extension
that eats
sysctl's output, an exception list that specifies
which

variables should be converted and to what format,
and does the conversion.

I understand that this is potentially N*M complexity
(N sysctl variables times M entries in the exception list)
if we allow exceptions to be regexp, but for the numbers
at hand it is probably acceptable.
The advantage is that you can run it on existing kernels
and can be easily customized.

c
heers
luigi
Bruce Evans
2015-04-07 07:11:10 UTC
Permalink
Post by Chris Torek
We had a side discussion at $work about a private sysctl emulation
(so our side thing doesn't actually affect sysctl itself at all)
where it was suggested that some simple numeric sysctls are "best
displayed in hex".
$ sysctl kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 65535
kern.timecounter.tc.i8254.counter: 25822
kern.timecounter.tc.i8254.frequency: 1193182
kern.timecounter.tc.i8254.quality: 0
The "mask" here actually makes more sense displayed in hex. One
$ sysctl -x kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 0x0000ffff
kern.timecounter.tc.i8254.counter: 0x0000786c
kern.timecounter.tc.i8254.frequency: 0x00000000001234de
kern.timecounter.tc.i8254.quality: 0000000000
but now the mask is shown in hex (yay) but the others are shown
in hex too (boo).
The suggestion made (note that I'm carefully filing off names via
#define CTLFLAG_DEFHEX 0x00000800
that says that, without any additional formatting directive, the
user-level "sysctl" command should output this particular value in
hex. Obviously this eats up another flag bit (but there are a few
left) and might require a new argument to the sysctl command
("force output to be decimal", for compatibility or whatever).
The format arg still exists. It used to be used to get unsigned and
hex formats, but is redundant for unsigned format and was rarely
used to specify hex format. Now it seems to only be used:
- for input, to distinguish between "IK" and other formats for
CTLTYPE_INT. ("IK" with other CTLTYPEs is only supported for
output)
- for output, to support 'K' and even more unparsable formats like
"S,clockinfo" and "S,vmtotal"

Getting hex format for a single special sysctl would have been almost
trivial when the X flag in the format was supported. Special cases
tend to need specially bloated dynamic attachment that needs 1 byte
to be changed to change the format string. For the example with
timecounters above:

X SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
X "mask", CTLFLAG_RD, &(tc->tc_counter_mask), 0,
X "mask for implemented bits");

SYSCTL_ADD_UINT() defaults a couple of parameters. Not enough to
make it less bloated, but enough to prevent you controlling its format
string.

X SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
X "counter", CTLTYPE_UINT | CTLFLAG_RD, tc, sizeof(*tc),
X sysctl_kern_timecounter_get, "IU", "current timecounter value");

Here it is trivial to change "IU" to "IX".

X SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
X "frequency", CTLTYPE_U64 | CTLFLAG_RD, tc, sizeof(*tc),
X sysctl_kern_timecounter_freq, "QU", "timecounter frequency");

This should use SYSCTL_ADD_UQUAD().
(The only differences are that it doesn't falsely claim to be MPSAFE,
and has a garbage size value.

Neither is MP safe on 32-bit arches, and the Giant locking given by
not claiming to be MPSAFE doesn't give any safeness for the 64-bit
variable accessed.

The garbage size value is apparently unused. The similar x86
machdep.tsc_freq sysctl has a garbage size value of 0, but this seems
to work too. In old versions, larger inconsistencies in the types
and sizes caused garbage reading the top 32 bits, but also made it
impossible to write these bits.

SYSCTL_*PROC() is harder to use than SYSCTL_*INTTYPE(), but using it
to specify a special ctltype or format is easy enough for a few uses.

Bruce
John Baldwin
2015-04-09 15:51:17 UTC
Permalink
Post by Chris Torek
We had a side discussion at $work about a private sysctl emulation
(so our side thing doesn't actually affect sysctl itself at all)
where it was suggested that some simple numeric sysctls are "best
displayed in hex".
We had this feature for hex and it was removed. 8.x still has SYSCTL_XINT()
and friends.

It was removed in
https://svnweb.freebsd.org/base?view=revision&revision=217586

The argument in that comment is that you should use sysctl -x. However, I
think that doesn't really wash. That is fine if you are looking at a single
node, but I think SYSCTL_XINT() was useful to set the default format that was
used for sysctl -a, etc. You could then have flags to sysctl to override it
for individual nodes for use in scripts, etc.
Post by Chris Torek
$ sysctl kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 65535
kern.timecounter.tc.i8254.counter: 25822
kern.timecounter.tc.i8254.frequency: 1193182
kern.timecounter.tc.i8254.quality: 0
The "mask" here actually makes more sense displayed in hex. One
$ sysctl -x kern.timecounter.tc.i8254
kern.timecounter.tc.i8254.mask: 0x0000ffff
kern.timecounter.tc.i8254.counter: 0x0000786c
kern.timecounter.tc.i8254.frequency: 0x00000000001234de
kern.timecounter.tc.i8254.quality: 0000000000
but now the mask is shown in hex (yay) but the others are shown
in hex too (boo).
Exactly.

I would support bringing the XINT variants back. Note that you would not want
to revert the above commit, but you would want to make the XINT variants use a
format of "X" and then fix sysctl(8) to handle "X" formats again.
--
John Baldwin
Loading...