drivers/md/dm-switch.c
Source file repositories/reference/linux-study-clean/drivers/md/dm-switch.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/md/dm-switch.c- Extension
.c- Size
- 15600 bytes
- Lines
- 578
- Domain
- Driver Families
- Bucket
- drivers/md
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/device-mapper.hlinux/module.hlinux/init.hlinux/vmalloc.h
Detected Declarations
struct switch_pathstruct switch_ctxfunction alloc_region_tablefunction switch_get_positionfunction switch_region_table_readfunction switch_get_path_nrfunction switch_region_table_writefunction initialise_region_tablefunction parse_pathfunction switch_dtrfunction switch_ctrfunction switch_mapfunction parse_hexfunction process_set_region_mappingsfunction switch_messagefunction switch_statusfunction switch_prepare_ioctlfunction switch_iterate_devices
Annotated Snippet
struct switch_path {
struct dm_dev *dmdev;
sector_t start;
};
/*
* Context block for a dm switch device.
*/
struct switch_ctx {
struct dm_target *ti;
unsigned int nr_paths; /* Number of paths in path_list. */
unsigned int region_size; /* Region size in 512-byte sectors */
unsigned long nr_regions; /* Number of regions making up the device */
signed char region_size_bits; /* log2 of region_size or -1 */
unsigned char region_table_entry_bits; /* Number of bits in one region table entry */
unsigned char region_entries_per_slot; /* Number of entries in one region table slot */
signed char region_entries_per_slot_bits; /* log2 of region_entries_per_slot or -1 */
region_table_slot_t *region_table; /* Region table */
/*
* Array of dm devices to switch between.
*/
struct switch_path path_list[];
};
static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned int nr_paths,
unsigned int region_size)
{
struct switch_ctx *sctx;
sctx = kzalloc_flex(*sctx, path_list, nr_paths);
if (!sctx)
return NULL;
sctx->ti = ti;
sctx->region_size = region_size;
ti->private = sctx;
return sctx;
}
static int alloc_region_table(struct dm_target *ti, unsigned int nr_paths)
{
struct switch_ctx *sctx = ti->private;
sector_t nr_regions = ti->len;
sector_t nr_slots;
if (!(sctx->region_size & (sctx->region_size - 1)))
sctx->region_size_bits = __ffs(sctx->region_size);
else
sctx->region_size_bits = -1;
sctx->region_table_entry_bits = 1;
while (sctx->region_table_entry_bits < sizeof(region_table_slot_t) * 8 &&
(region_table_slot_t)1 << sctx->region_table_entry_bits < nr_paths)
sctx->region_table_entry_bits++;
sctx->region_entries_per_slot = (sizeof(region_table_slot_t) * 8) / sctx->region_table_entry_bits;
if (!(sctx->region_entries_per_slot & (sctx->region_entries_per_slot - 1)))
sctx->region_entries_per_slot_bits = __ffs(sctx->region_entries_per_slot);
else
sctx->region_entries_per_slot_bits = -1;
if (sector_div(nr_regions, sctx->region_size))
nr_regions++;
if (nr_regions >= ULONG_MAX) {
ti->error = "Region table too large";
return -EINVAL;
}
sctx->nr_regions = nr_regions;
nr_slots = nr_regions;
if (sector_div(nr_slots, sctx->region_entries_per_slot))
nr_slots++;
if (nr_slots > ULONG_MAX / sizeof(region_table_slot_t)) {
ti->error = "Region table too large";
return -EINVAL;
}
sctx->region_table = vmalloc_array(nr_slots,
sizeof(region_table_slot_t));
if (!sctx->region_table) {
ti->error = "Cannot allocate region table";
Annotation
- Immediate include surface: `linux/device-mapper.h`, `linux/module.h`, `linux/init.h`, `linux/vmalloc.h`.
- Detected declarations: `struct switch_path`, `struct switch_ctx`, `function alloc_region_table`, `function switch_get_position`, `function switch_region_table_read`, `function switch_get_path_nr`, `function switch_region_table_write`, `function initialise_region_table`, `function parse_path`, `function switch_dtr`.
- Atlas domain: Driver Families / drivers/md.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.