Could you try running the following program, as shown on the third line (if you save it as this.c)?
// Spdx-License-Identifier: CC0-1.0
//
// gcc -Wall -O2 this.c -o showioprio && ./showioprio $(cd /proc && /bin/ls -1d [1-9]* | tr -d /) | sort -n
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int report(pid_t p)
{
errno = 0;
long val = syscall(SYS_ioprio_get, /*IOPRIO_WHO_PROCESS*/ 1, (int)p);
if (errno) {
if (errno == ESRCH) {
fprintf(stderr, "%d: No such process.\n", (int)p);
return 0;
} else {
fprintf(stderr, "%d: ioprio_get syscall failed: %s.\n", (int)p, strerror(errno));
return -1;
}
}
long c = val >> 13;
if (c == 0) {
errno = 0;
int n = getpriority(PRIO_PROCESS, p);
if (errno) {
fprintf(stderr, "%d: getpriority() failed: %s.\n", (int)p, strerror(errno));
return -1;
}
if (n < -20 || n > 19) {
fprintf(stderr, "%d: getpriority() returned an invalid scheduling priority, %d.\n", (int)p, n);
return -1;
}
int v = (n + 20) / 5; /* Specified as the mapping between scheduling priority and IO priority */
int s = sched_getscheduler(p);
switch (s & 0x3FFFFFFF) {
case -1:
fprintf(stderr, "%d: sched_getscheduler() failed: %s.\n", (int)p, strerror(errno));
return -1;
case SCHED_FIFO:
case SCHED_RR:
case SCHED_DEADLINE:
printf("%d: Realtime %d (default)\n", (int)p, v);
break;
case SCHED_IDLE:
printf("%d: Idle %d (default)\n", (int)p, v);
break;
default:
printf("%d: Best-effort %d (default)\n", (int)p, v);
break;
}
fflush(stdout);
return 0;
} else {
int v = val & 0x1FFF;
if (v < 0 || v > 7) {
printf("%d: Unknown ioprio 0x%lx\n", (int)p, (unsigned long)val);
fflush(stdout);
return -1;
}
switch (c) {
case 1: printf("%d: Realtime %d\n", (int)p, v);
break;
case 2: printf("%d: Best-effort %d\n", (int)p, v);
break;
case 3: printf("%d: Idle %d\n", (int)p, v);
break;
default: fprintf(stderr, "%d: Unknown ioprio 0x%lx\n", (int)p, (unsigned long)val);
return -1;
}
fflush(stdout);
return 0;
}
}
int parse_pid(const char *src, pid_t *to)
{
const char *end;
long val;
if (!src || !*src)
return errno = EINVAL;
errno = 0;
end = src;
val = strtol(src, (char **)(&end), 0);
if (errno)
return errno;
if (src == end || *end || (long)((pid_t)val) != val)
return errno = EINVAL;
if (to)
*to = (pid_t)val;
return 0;
}
int main(int argc, char *argv[])
{
pid_t p;
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s -h | --help\n", argv[0]);
fprintf(stderr, " %s PID [ PID ... ]\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This reports the IO class and priority for the specified process or processes.\n");
fprintf(stderr, "\n");
}
if (argc < 2) {
if (report(getpid()))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
for (int arg = 1; arg < argc; arg++) {
if (parse_pid(argv[arg], &p) || p < 1) {
fprintf(stderr, "%s: Invalid process ID: %s.\n", argv[arg], strerror(errno));
return EXIT_FAILURE;
}
if (report(p))
return EXIT_FAILURE;
fflush(stdout);
}
return EXIT_SUCCESS;
}
It uses the same logic as the current kernel (as of 2023-03-17): class zero indicates I/O priority is derived from CPU priority via (nice+20)/5 (in which case the value part is irrelevant); if CPU scheduling policy is SCHED_IDLE, then the I/O priority class is idle also; if SCHED_FIFO, SCHED_RR, or SCHED_DEADLINE, then the I/O priority class is realtime; otherwise the I/O priority class is best effort.
All processes running on my desktop machine report one of
Best-effort 0 (default)
Best-effort 1 (default)
Best-effort 2 (default)
Best-effort 3
Best-effort 3 (default)
Best-effort 4 (default)
Best-effort 5 (default)
Best-effort 7 (default)
Realtime 4 (default)
where the (default) just denotes that the I/O priority was not set explicitly, but was inherited from the default CPU priority as mentioned above.
Running the example command it is normal for it to report three or so PIDs as not existing, because they have been reaped before the example program runs.
Any error messages output to standard error would be interesting; I only get three "No such process." ones.
In particular, check out for "Function not implemented" and "Operation not supported" errors.