Skip to content

ionice: should the port enforce the documented ranges for -c and -n? #624

Description

@mmclinton

I have ionice working locally and can open a PR shortly. One choice is worth putting to you first, because both answers are defensible and the difference is visible to users.

ionice(1) gives -c as "0 for none, 1 for realtime, 2 for best-effort, 3 for idle" and -n as a level of 0-7. util-linux 2.42.2 enforces neither, and out-of-range values can result in unexpected behavior like selecting a different scheduling class.

-n above 8191 can change the class, with nothing printed:

$ ionice -n 8191 ionice
best-effort: prio 8191
$ ionice -n 8192 ionice
idle

The second case asked for best-effort and got idle. ionice -c 2 -n 16384 ionice reports best-effort: prio 0, so the prio level asked for is simply disregarded.

-c above 3 behaves as the class number modulo 8. Not every value gets past the kernel (-c 12 fails with ioprio_set failed: Invalid argument), but values that wrap onto best-effort or idle take effect and report success:

$ ionice -c 10 ionice
ionice: unknown prio class 10
best-effort: prio 4
$ ionice -c 11 ionice
ionice: unknown prio class 11
idle
$ echo $?
0

That is on a live process too, not just a read-back; ionice -c 11 -p PID moves a process from none to idle and exits 0. With -t there is no diagnostic at all, because -t silences that warning:

$ ionice -t -c 99 ionice
idle

So this port has to pick one:

  1. Replicate util-linux behavior exactly, accepting any value.
  2. Enforce the documented ranges and reject anything outside them.

I lean towards 2. Being told a class is unknown and then landing in it anyway, with exit status 0, is hard to notice and hard to debug, and both the man page and --help are clear about the ranges. The accepted values do not even mean what they read as: probing the raw syscalls on Linux 6.18, the kernel evaluates the level modulo 8, so the prio 8191 above is level 7, the lowest documented priority, while -n 8, one past the bottom of the documented range, is effectively level 0, the highest best-effort priority. But enforcing the ranges is a deliberate, user-visible divergence from util-linux, and that did not seem like a call to make silently inside a PR.

My local branch currently does 1, on the principle that a port should not change behavior without a reason, and that is what I will open the PR with unless somebody prefers otherwise. Happy to switch it to 2 at any point; it is a small change either way.

p.s. I believe this is the only conformance question in the tool, though continued black-box probing could always turn up another.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions