Files
systemd/src/shared/blockdev-list.h
T
Lennart Poettering 5af1038123 blockdev-list: split per-device filtering into blockdev_list_one()
Subscribers to block-device uevents need to apply the same filter set
blockdev_list() uses over the bulk enumeration, one device at a time.
Pull the per-device body out as blockdev_list_one(), expose
blockdev_list_get_root_devnos() so callers can compute the IGNORE_ROOT
devnos once up-front, and introduce a 4-valued return code so callers
can distinguish:

  MATCH_NO       - fails a static filter (subsystem, ZRAM, IGNORE_ROOT,
                   REQUIRE_PARTITION_SCANNING, REQUIRE_LUKS)
  MATCH_YES      - fully matches
  MATCH_FILTERED - passes static filters but fails a dynamic one
                   (IGNORE_EMPTY, IGNORE_READ_ONLY) - useful to surface
                   as "device just became invisible" transitions when
                   the kernel flips size/ro at runtime
  MATCH_SKIPPED  - soft error during filter evaluation; callers should
                   treat this like MATCH_FILTERED, but the distinct code
                   makes the soft failure visible rather than silently
                   swallowed inside blockdev_list_one()

*ret is initialized on every non-negative return (BLOCK_DEVICE_NULL for
MATCH_NO / MATCH_SKIPPED, fully populated for MATCH_YES / MATCH_FILTERED),
and untouched on negative return. blockdev_list() itself collapses
everything except MATCH_YES back into "skip", so existing callers see
no behavior change.
2026-06-01 11:26:06 +02:00

67 lines
3.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "basic-forward.h"
#include "shared-forward.h"
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_ZRAM = 1 << 2, /* Ignore ZRAM */
BLOCKDEV_LIST_REQUIRE_LUKS = 1 << 3, /* Only consider block devices with LUKS superblocks */
BLOCKDEV_LIST_IGNORE_ROOT = 1 << 4, /* Ignore the block device we are currently booted from */
BLOCKDEV_LIST_IGNORE_EMPTY = 1 << 5, /* Ignore disks of zero size (usually drives without a medium) */
BLOCKDEV_LIST_METADATA = 1 << 6, /* Fill in model, vendor, subsystem, read_only */
BLOCKDEV_LIST_IGNORE_READ_ONLY = 1 << 7, /* Ignore read-only block devices */
} BlockDevListFlags;
/* The "dynamic" filters – ones the kernel can flip at runtime via sysattrs on a live device.
* Useful for callers that want to distinguish "device is hard-filtered (never interesting)" from
* "device just transitioned in or out of the candidate set". */
#define BLOCKDEV_LIST_DYNAMIC_FILTERS_MASK \
(BLOCKDEV_LIST_IGNORE_EMPTY | BLOCKDEV_LIST_IGNORE_READ_ONLY)
typedef struct BlockDevice {
char *node;
char **symlinks;
char *model;
char *vendor;
char *subsystem;
uint64_t diskseq;
uint64_t size; /* in bytes */
int read_only;
} BlockDevice;
#define BLOCK_DEVICE_NULL (BlockDevice) { \
.diskseq = UINT64_MAX, \
.size = UINT64_MAX, \
.read_only = -1, \
}
/* Return values of blockdev_list_one(). Not its own type – returned as int. */
enum {
BLOCKDEV_LIST_MATCH_NO, /* Hard-filtered out by a static filter (subsystem, ZRAM,
* IGNORE_ROOT, REQUIRE_PARTITION_SCANNING, REQUIRE_LUKS, …). */
BLOCKDEV_LIST_MATCH_YES, /* Passes all filters. */
BLOCKDEV_LIST_MATCH_FILTERED, /* Passes the static filters; fails at least one dynamic filter
* (IGNORE_EMPTY, IGNORE_READ_ONLY). */
BLOCKDEV_LIST_MATCH_SKIPPED, /* Filter evaluation hit an unexpected error (failed sysattr
* read, missing devname, …). Callers should typically treat
* this like _FILTERED (device not currently a candidate),
* but distinguishing it makes the soft failure visible
* rather than silently swallowed inside blockdev_list_one(). */
};
void block_device_done(BlockDevice *d);
void block_device_array_free(BlockDevice *d, size_t n_devices);
int blockdev_list_get_root_devnos(BlockDevListFlags flags, dev_t *ret_root, dev_t *ret_whole_root);
int blockdev_list_one(
sd_device *dev,
BlockDevListFlags flags,
dev_t root_devno,
dev_t whole_root_devno,
BlockDevice *ret);
int blockdev_list(BlockDevListFlags flags, BlockDevice **ret_devices, size_t *ret_n_devices);