From 48a9afb6eca06f8bf7434cd907af02cdabb75ecb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Sep 2026 12:06:58 +0200 Subject: [PATCH] blockdev-list: split BLOCKDEV_LIST_IGNORE_LOOP out of BLOCKDEV_LIST_IGNORE_VIRTUAL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far BLOCKDEV_LIST_IGNORE_VIRTUAL filtered out everything below /sys/devices/virtual/, which includes loopback devices. Loopback devices are frequently used as stand-ins for real disks though (in tests, and when installing to disk images), hence it's useful to be able to control them independently of the other virtual devices (dm, md, zram, …). Introduce a separate BLOCKDEV_LIST_IGNORE_LOOP flag for loopback devices, and make BLOCKDEV_LIST_IGNORE_VIRTUAL only cover the non-loop virtual devices. The only existing user (systemd-report) is updated to pass both flags, so that its behaviour stays unchanged. --- src/report/report-basic.c | 2 +- src/shared/blockdev-list.c | 17 ++++++++++++++++- src/shared/blockdev-list.h | 21 +++++++++++---------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/report/report-basic.c b/src/report/report-basic.c index 4b8d9ce024..eb2fe6a498 100644 --- a/src/report/report-basic.c +++ b/src/report/report-basic.c @@ -384,7 +384,7 @@ static int disk_io_generate(const MetricFamily mf[static 2], sd_varlink *link, v size_t n_devices = 0; CLEANUP_ARRAY(devices, n_devices, block_device_array_free); - r = blockdev_list(BLOCKDEV_LIST_IGNORE_VIRTUAL | BLOCKDEV_LIST_IGNORE_PARTITIONS | BLOCKDEV_LIST_RW_STATS, + r = blockdev_list(BLOCKDEV_LIST_IGNORE_VIRTUAL | BLOCKDEV_LIST_IGNORE_LOOP | BLOCKDEV_LIST_IGNORE_PARTITIONS | BLOCKDEV_LIST_RW_STATS, &devices, &n_devices); if (r < 0) return r; diff --git a/src/shared/blockdev-list.c b/src/shared/blockdev-list.c index fe71bd4ccc..e44332dc60 100644 --- a/src/shared/blockdev-list.c +++ b/src/shared/blockdev-list.c @@ -167,7 +167,22 @@ int blockdev_list_one( goto no_match; } - if (FLAGS_SET(flags, BLOCKDEV_LIST_IGNORE_VIRTUAL)) { + bool is_loop = false; + if (flags & (BLOCKDEV_LIST_IGNORE_LOOP|BLOCKDEV_LIST_IGNORE_VIRTUAL)) { + r = device_sysname_startswith(dev, "loop"); + if (r < 0) { + log_device_warning_errno(dev, r, "Failed to check device name of discovered block device '%s', ignoring: %m", node); + goto skipped; + } + + is_loop = r > 0; + if (is_loop && FLAGS_SET(flags, BLOCKDEV_LIST_IGNORE_LOOP)) + goto no_match; + } + + /* Loopback devices are virtual devices too, but they are covered by BLOCKDEV_LIST_IGNORE_LOOP above, + * hence exclude them here. */ + if (FLAGS_SET(flags, BLOCKDEV_LIST_IGNORE_VIRTUAL) && !is_loop) { const char *devpath; r = sd_device_get_devpath(dev, &devpath); diff --git a/src/shared/blockdev-list.h b/src/shared/blockdev-list.h index e79ad74a76..c50745abbb 100644 --- a/src/shared/blockdev-list.h +++ b/src/shared/blockdev-list.h @@ -6,16 +6,17 @@ typedef enum BlockDevListFlags { BLOCKDEV_LIST_SHOW_SYMLINKS = 1 << 0, /* Pick up symlinks to block devices too */ BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING = 1 << 1, /* Only consider block devices with partition scanning */ - BLOCKDEV_LIST_IGNORE_VIRTUAL = 1 << 2, /* Ignore virtual devices (devices under /sys/devices/virtual/) */ - BLOCKDEV_LIST_IGNORE_PARTITIONS = 1 << 3, /* Ignore partitions */ - BLOCKDEV_LIST_IGNORE_ZRAM = 1 << 4, /* Ignore ZRAM */ - BLOCKDEV_LIST_IGNORE_ROOT = 1 << 5, /* Ignore the block device we are currently booted from */ - BLOCKDEV_LIST_IGNORE_EMPTY = 1 << 6, /* Ignore disks of zero size (usually drives without a medium) */ - BLOCKDEV_LIST_IGNORE_READ_ONLY = 1 << 7, /* Ignore read-only block devices */ - BLOCKDEV_LIST_REQUIRE_LUKS = 1 << 8, /* Only consider block devices with LUKS superblocks */ - BLOCKDEV_LIST_METADATA = 1 << 9, /* Fill in model, vendor, subsystem, read_only */ - BLOCKDEV_LIST_DISKSEQ = 1 << 10, /* Fill in the diskseq field */ - BLOCKDEV_LIST_RW_STATS = 1 << 11, /* Fill in read and write measurements */ + BLOCKDEV_LIST_IGNORE_VIRTUAL = 1 << 2, /* Ignore virtual devices (devices under /sys/devices/virtual/), except loopback devices */ + BLOCKDEV_LIST_IGNORE_LOOP = 1 << 3, /* Ignore loopback devices */ + BLOCKDEV_LIST_IGNORE_PARTITIONS = 1 << 4, /* Ignore partitions */ + BLOCKDEV_LIST_IGNORE_ZRAM = 1 << 5, /* Ignore ZRAM */ + BLOCKDEV_LIST_IGNORE_ROOT = 1 << 6, /* Ignore the block device we are currently booted from */ + BLOCKDEV_LIST_IGNORE_EMPTY = 1 << 7, /* Ignore disks of zero size (usually drives without a medium) */ + BLOCKDEV_LIST_IGNORE_READ_ONLY = 1 << 8, /* Ignore read-only block devices */ + BLOCKDEV_LIST_REQUIRE_LUKS = 1 << 9, /* Only consider block devices with LUKS superblocks */ + BLOCKDEV_LIST_METADATA = 1 << 10, /* Fill in model, vendor, subsystem, read_only */ + BLOCKDEV_LIST_DISKSEQ = 1 << 11, /* Fill in the diskseq field */ + BLOCKDEV_LIST_RW_STATS = 1 << 12, /* Fill in read and write measurements */ } BlockDevListFlags; /* The "dynamic" filters – ones the kernel can flip at runtime via sysattrs on a live device.