Lines Matching +full:1 +full:- +full:255

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2010-2012 by Dell Inc. All rights reserved.
4 * Copyright (C) 2011-2013 Red Hat, Inc.
8 * dm-switch is a device-mapper target that maps IO to underlying block
9 * devices efficiently when there are a large number of fixed-sized
11 * mapping representation such as dm-stripe.
14 #include <linux/device-mapper.h>
44 unsigned int region_size; /* Region size in 512-byte sectors */
46 signed char region_size_bits; /* log2 of region_size or -1 */
50 signed char region_entries_per_slot_bits; /* log2 of region_entries_per_slot or -1 */
69 sctx->ti = ti; in alloc_switch_ctx()
70 sctx->region_size = region_size; in alloc_switch_ctx()
72 ti->private = sctx; in alloc_switch_ctx()
79 struct switch_ctx *sctx = ti->private; in alloc_region_table()
80 sector_t nr_regions = ti->len; in alloc_region_table()
83 if (!(sctx->region_size & (sctx->region_size - 1))) in alloc_region_table()
84 sctx->region_size_bits = __ffs(sctx->region_size); in alloc_region_table()
86 sctx->region_size_bits = -1; in alloc_region_table()
88 sctx->region_table_entry_bits = 1; in alloc_region_table()
89 while (sctx->region_table_entry_bits < sizeof(region_table_slot_t) * 8 && in alloc_region_table()
90 (region_table_slot_t)1 << sctx->region_table_entry_bits < nr_paths) in alloc_region_table()
91 sctx->region_table_entry_bits++; in alloc_region_table()
93 sctx->region_entries_per_slot = (sizeof(region_table_slot_t) * 8) / sctx->region_table_entry_bits; in alloc_region_table()
94 if (!(sctx->region_entries_per_slot & (sctx->region_entries_per_slot - 1))) in alloc_region_table()
95 sctx->region_entries_per_slot_bits = __ffs(sctx->region_entries_per_slot); in alloc_region_table()
97 sctx->region_entries_per_slot_bits = -1; in alloc_region_table()
99 if (sector_div(nr_regions, sctx->region_size)) in alloc_region_table()
103 ti->error = "Region table too large"; in alloc_region_table()
104 return -EINVAL; in alloc_region_table()
106 sctx->nr_regions = nr_regions; in alloc_region_table()
109 if (sector_div(nr_slots, sctx->region_entries_per_slot)) in alloc_region_table()
113 ti->error = "Region table too large"; in alloc_region_table()
114 return -EINVAL; in alloc_region_table()
117 sctx->region_table = vmalloc(array_size(nr_slots, in alloc_region_table()
119 if (!sctx->region_table) { in alloc_region_table()
120 ti->error = "Cannot allocate region table"; in alloc_region_table()
121 return -ENOMEM; in alloc_region_table()
130 if (sctx->region_entries_per_slot_bits >= 0) { in switch_get_position()
131 *region_index = region_nr >> sctx->region_entries_per_slot_bits; in switch_get_position()
132 *bit = region_nr & (sctx->region_entries_per_slot - 1); in switch_get_position()
134 *region_index = region_nr / sctx->region_entries_per_slot; in switch_get_position()
135 *bit = region_nr % sctx->region_entries_per_slot; in switch_get_position()
138 *bit *= sctx->region_table_entry_bits; in switch_get_position()
148 return (READ_ONCE(sctx->region_table[region_index]) >> bit) & in switch_region_table_read()
149 ((1 << sctx->region_table_entry_bits) - 1); in switch_region_table_read()
161 if (sctx->region_size_bits >= 0) in switch_get_path_nr()
162 p >>= sctx->region_size_bits; in switch_get_path_nr()
164 sector_div(p, sctx->region_size); in switch_get_path_nr()
168 /* This can only happen if the processor uses non-atomic stores. */ in switch_get_path_nr()
169 if (unlikely(path_nr >= sctx->nr_paths)) in switch_get_path_nr()
184 pte = sctx->region_table[region_index]; in switch_region_table_write()
185 pte &= ~((((region_table_slot_t)1 << sctx->region_table_entry_bits) - 1) << bit); in switch_region_table_write()
187 sctx->region_table[region_index] = pte; in switch_region_table_write()
198 for (region_nr = 0; region_nr < sctx->nr_regions; region_nr++) { in initialise_region_table()
200 if (++path_nr >= sctx->nr_paths) in initialise_region_table()
207 struct switch_ctx *sctx = ti->private; in parse_path()
211 r = dm_get_device(ti, dm_shift_arg(as), dm_table_get_mode(ti->table), in parse_path()
212 &sctx->path_list[sctx->nr_paths].dmdev); in parse_path()
214 ti->error = "Device lookup failed"; in parse_path()
219 ti->error = "Invalid device starting offset"; in parse_path()
220 dm_put_device(ti, sctx->path_list[sctx->nr_paths].dmdev); in parse_path()
221 return -EINVAL; in parse_path()
224 sctx->path_list[sctx->nr_paths].start = start; in parse_path()
226 sctx->nr_paths++; in parse_path()
232 * Destructor: Don't free the dm_target, just the ti->private data (if any).
236 struct switch_ctx *sctx = ti->private; in switch_dtr()
238 while (sctx->nr_paths--) in switch_dtr()
239 dm_put_device(ti, sctx->path_list[sctx->nr_paths].dmdev); in switch_dtr()
241 vfree(sctx->region_table); in switch_dtr()
256 …{1, (KMALLOC_MAX_SIZE - sizeof(struct switch_ctx)) / sizeof(struct switch_path), "Invalid number o… in switch_ctr()
257 {1, UINT_MAX, "Invalid region size"}, in switch_ctr()
269 r = dm_read_arg(_args, &as, &nr_paths, &ti->error); in switch_ctr()
271 return -EINVAL; in switch_ctr()
273 r = dm_read_arg(_args + 1, &as, &region_size, &ti->error); in switch_ctr()
277 r = dm_read_arg_group(_args + 2, &as, &nr_optional_args, &ti->error); in switch_ctr()
283 ti->error = "Incorrect number of path arguments"; in switch_ctr()
284 return -EINVAL; in switch_ctr()
289 ti->error = "Cannot allocate redirection context"; in switch_ctr()
290 return -ENOMEM; in switch_ctr()
310 ti->num_discard_bios = 1; in switch_ctr()
322 struct switch_ctx *sctx = ti->private; in switch_map()
323 sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector); in switch_map()
326 bio_set_dev(bio, sctx->path_list[path_nr].dmdev->bdev); in switch_map()
327 bio->bi_iter.bi_sector = sctx->path_list[path_nr].start + offset; in switch_map()
335 * This table-based hex parser improves performance.
336 * It improves a time to load 1000000 entries compared to the condition-based
338 * table-based parser condition-based parser
339 * PA-RISC 0.29s 0.31s
343 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
344 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
345 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
346 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
347 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
348 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
349 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
350 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
351 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
352 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
353 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
354 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
355 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
356 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
357 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
358 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
380 for (i = 1; i < argc; i++) { in process_set_region_mappings()
390 return -EINVAL; in process_set_region_mappings()
395 return -EINVAL; in process_set_region_mappings()
400 return -EINVAL; in process_set_region_mappings()
405 return -EINVAL; in process_set_region_mappings()
408 if (unlikely(!cycle_length) || unlikely(cycle_length - 1 > region_index)) { in process_set_region_mappings()
410 cycle_length - 1, region_index); in process_set_region_mappings()
411 return -EINVAL; in process_set_region_mappings()
414 unlikely(region_index + num_write >= sctx->nr_regions)) { in process_set_region_mappings()
416 region_index, num_write, sctx->nr_regions); in process_set_region_mappings()
417 return -EINVAL; in process_set_region_mappings()
420 while (num_write--) { in process_set_region_mappings()
422 path_nr = switch_region_table_read(sctx, region_index - cycle_length); in process_set_region_mappings()
435 return -EINVAL; in process_set_region_mappings()
442 return -EINVAL; in process_set_region_mappings()
448 return -EINVAL; in process_set_region_mappings()
450 if (unlikely(region_index >= sctx->nr_regions)) { in process_set_region_mappings()
451 DMWARN("invalid set_region_mappings region number: %lu >= %lu", region_index, sctx->nr_regions); in process_set_region_mappings()
452 return -EINVAL; in process_set_region_mappings()
454 if (unlikely(path_nr >= sctx->nr_paths)) { in process_set_region_mappings()
455 DMWARN("invalid set_region_mappings device: %lu >= %u", path_nr, sctx->nr_paths); in process_set_region_mappings()
456 return -EINVAL; in process_set_region_mappings()
466 * Messages are processed one-at-a-time.
475 struct switch_ctx *sctx = ti->private; in switch_message()
476 int r = -EINVAL; in switch_message()
493 struct switch_ctx *sctx = ti->private; in switch_status()
503 DMEMIT("%u %u 0", sctx->nr_paths, sctx->region_size); in switch_status()
504 for (path_nr = 0; path_nr < sctx->nr_paths; path_nr++) in switch_status()
505 DMEMIT(" %s %llu", sctx->path_list[path_nr].dmdev->name, in switch_status()
506 (unsigned long long)sctx->path_list[path_nr].start); in switch_status()
522 struct switch_ctx *sctx = ti->private; in switch_prepare_ioctl()
527 *bdev = sctx->path_list[path_nr].dmdev->bdev; in switch_prepare_ioctl()
532 if (ti->len + sctx->path_list[path_nr].start != in switch_prepare_ioctl()
534 return 1; in switch_prepare_ioctl()
541 struct switch_ctx *sctx = ti->private; in switch_iterate_devices()
545 for (path_nr = 0; path_nr < sctx->nr_paths; path_nr++) { in switch_iterate_devices()
546 r = fn(ti, sctx->path_list[path_nr].dmdev, in switch_iterate_devices()
547 sctx->path_list[path_nr].start, ti->len, data); in switch_iterate_devices()
557 .version = {1, 1, 0},