Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: flag/bitfield pretty printers #15945

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft

Conversation

robn
Copy link
Contributor

@robn robn commented Feb 29, 2024

Motivation and Context

As a good C program, OpenZFS uses bitfields everywhere. I am extremely bad at decoding these in my head, so I frequently find myself writing weird custom formatters. Today I finally got sick of that, so I had a go at making some formatting facilities for bitfields.

I'm looking for code review, suggestions for improvements and any other thoughts you might have. It might be that a generic facility isn't worth it, but it'd be nice to have something available we can reach for for the common cases, and as you see, there's opportunity to improve user tools as well.

Description

In the commits you will find zfs_pretty, which is a bunch of tables that describe display styles for a handful of bitfield types, and functions to take a value and format it. There's three display styles available for each value: a single character, a character pair, and a full name.

There's then three example applications, which I will show here.

When we've got plenty of space to work with and/or being explicit is important, there's a full expansion mode available (zfs_pretty_<type>_str()). An example is when showing ZIO contents in zio_events after an error:

Feb 29 2024 04:56:28.413337691 ereport.fs.zfs.data
...
        zio_err = 0x5
        zio_flags = 0x8181 [DONT_AGGREGATE CANFAIL SPECULATIVE PROBE]
        zio_stage = 0x2000000

When a much tighter format is wanted, there's a one-char-per-bit mode available (zfs_pretty_<type>_bits()). This is likely to be more useful for types with relatively few defined bits, as there's a limited number of unambiguous characters available. However, since unset bits are shown as blank space, this mode may still be useful in some cases as a visual representation of shape or sequence. This example shows something I do pretty often, which is to dump bits of ZIOs or ABDs in flight:

[    3.986551] NOTICE: zio_ready: zio 00000000b250d408 type 2 flags [             ..        ..     .]; abd 00000000acb026fc size 00002000 flags [ A   P  MOL]
[    3.987872] NOTICE: zio_ready: zio 000000004afb4d15 type 1 flags [                     ....      ]; abd 00000000acb026fc size 0001c000 flags [ A      MOL]
[    4.009248] NOTICE: zio_ready: zio 0000000050402b45 type 2 flags [                     . ..      ]; abd 000000002d5d83f2 size 0001c000 flags [ A      MOL]
[    4.009463] NOTICE: zio_ready: zio 00000000865d0834 type 2 flags [                     . ..      ]; abd 000000001d844cd8 size 00002000 flags [ A   P  MOL]
[    4.017214] NOTICE: zio_ready: zio 000000009a426bbb type 2 flags [                .              ]; abd 00000000beda36e4 size 00000200 flags [ A        L]
[    4.017377] NOTICE: zio_ready: zio 0000000068990b19 type 2 flags [                               ]; abd 0000000076fe7aa3 size 00000200 flags [ A        L]

Finally, there's a compact "pairs" mode (zfs_pretty_<type>_pairs()), which has two chars per bit, with a visual separator. This can work well when there's too many bits defined for the "bits" mode to be useful, but there's still a limited amount of space available. Here's an example showing ARC header flags in the dbuf stats:

# cat /proc/spl/kstat/zfs/dbufs | perl -F'/\s+\|\s+/' -lanE 'print $F[1]'

arcbuf
list  atype flags                count  asize    access       mru    gmru   mfu    gmfu   l2     l2_dattr l2_asize l2_comp  aholds
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294893222   0      0      0      0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      512      4294894529   0      0      0      0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294893229   0      0      0      0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294894530   0      0      0      0      0      0        0        0        1
3     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      512      4294932928   11     0      33     0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294894529   0      0      0      0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294894530   0      0      0      0      0      0        0        0        1
1     1     C3|C2|C1|C0|CA|1H|MD|HT|2C 1      1024     4294894530   0      0      0      0      0      0        0        0        1
1     0     C1|CA|1H|HT|2C       1      131072   4294893229   0      0      0      0      0      0        0        0        1
1     0     C1|CA|1H|HT|2C       1      131072   4294893229   0      0      0      0      0      0        0        0        1
1     0     C1|CA|1H|HT|2C       1      131072   4294893229   0      0      0      0      0      0        0        0        1
1     0     C1|CA|1H|HT|2C       1      131072   4294893229   0      0      0      0      0      0        0        0        1

I don't claim that these are good uses (well, I like the zpool events one); they were just convenient ways to show what's going on.

(I will spare you further experiments involving colour and emojis ... for now!)

How Has This Been Tested?

Draft, so minimal; just hand testing for now.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
@robn robn marked this pull request as draft February 29, 2024 05:16
@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label Apr 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Code Review Needed Ready for review and testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants