dm-stripe.c revision 1df05483d758ea43abc375869fbe06be506ba827
1/* 2 * Copyright (C) 2001-2003 Sistina Software (UK) Limited. 3 * 4 * This file is released under the GPL. 5 */ 6 7#include <linux/device-mapper.h> 8 9#include <linux/module.h> 10#include <linux/init.h> 11#include <linux/blkdev.h> 12#include <linux/bio.h> 13#include <linux/slab.h> 14#include <linux/log2.h> 15 16#define DM_MSG_PREFIX "striped" 17#define DM_IO_ERROR_THRESHOLD 15 18 19struct stripe { 20 struct dm_dev *dev; 21 sector_t physical_start; 22 23 atomic_t error_count; 24}; 25 26struct stripe_c { 27 uint32_t stripes; 28 int stripes_shift; 29 30 /* The size of this target / num. stripes */ 31 sector_t stripe_width; 32 33 /* stripe chunk size */ 34 uint32_t chunk_shift; 35 sector_t chunk_mask; 36 37 /* Needed for handling events */ 38 struct dm_target *ti; 39 40 /* Work struct used for triggering events*/ 41 struct work_struct trigger_event; 42 43 struct stripe stripe[0]; 44}; 45 46/* 47 * An event is triggered whenever a drive 48 * drops out of a stripe volume. 49 */ 50static void trigger_event(struct work_struct *work) 51{ 52 struct stripe_c *sc = container_of(work, struct stripe_c, 53 trigger_event); 54 dm_table_event(sc->ti->table); 55} 56 57static inline struct stripe_c *alloc_context(unsigned int stripes) 58{ 59 size_t len; 60 61 if (dm_array_too_big(sizeof(struct stripe_c), sizeof(struct stripe), 62 stripes)) 63 return NULL; 64 65 len = sizeof(struct stripe_c) + (sizeof(struct stripe) * stripes); 66 67 return kmalloc(len, GFP_KERNEL); 68} 69 70/* 71 * Parse a single <dev> <sector> pair 72 */ 73static int get_stripe(struct dm_target *ti, struct stripe_c *sc, 74 unsigned int stripe, char **argv) 75{ 76 unsigned long long start; 77 char dummy; 78 79 if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1) 80 return -EINVAL; 81 82 if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), 83 &sc->stripe[stripe].dev)) 84 return -ENXIO; 85 86 sc->stripe[stripe].physical_start = start; 87 88 return 0; 89} 90 91/* 92 * Construct a striped mapping. 93 * <number of stripes> <chunk size (2^^n)> [<dev_path> <offset>]+ 94 */ 95static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) 96{ 97 struct stripe_c *sc; 98 sector_t width; 99 uint32_t stripes; 100 uint32_t chunk_size; 101 int r; 102 unsigned int i; 103 104 if (argc < 2) { 105 ti->error = "Not enough arguments"; 106 return -EINVAL; 107 } 108 109 if (kstrtouint(argv[0], 10, &stripes) || !stripes) { 110 ti->error = "Invalid stripe count"; 111 return -EINVAL; 112 } 113 114 if (kstrtouint(argv[1], 10, &chunk_size)) { 115 ti->error = "Invalid chunk_size"; 116 return -EINVAL; 117 } 118 119 /* 120 * chunk_size is a power of two 121 */ 122 if (!is_power_of_2(chunk_size) || 123 (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { 124 ti->error = "Invalid chunk size"; 125 return -EINVAL; 126 } 127 128 if (ti->len & (chunk_size - 1)) { 129 ti->error = "Target length not divisible by " 130 "chunk size"; 131 return -EINVAL; 132 } 133 134 if (sector_div(width, stripes)) { 135 ti->error = "Target length not divisible by " 136 "number of stripes"; 137 return -EINVAL; 138 } 139 140 /* 141 * Do we have enough arguments for that many stripes ? 142 */ 143 if (argc != (2 + 2 * stripes)) { 144 ti->error = "Not enough destinations " 145 "specified"; 146 return -EINVAL; 147 } 148 149 sc = alloc_context(stripes); 150 if (!sc) { 151 ti->error = "Memory allocation for striped context " 152 "failed"; 153 return -ENOMEM; 154 } 155 156 INIT_WORK(&sc->trigger_event, trigger_event); 157 158 /* Set pointer to dm target; used in trigger_event */ 159 sc->ti = ti; 160 sc->stripes = stripes; 161 sc->stripe_width = width; 162 163 if (stripes & (stripes - 1)) 164 sc->stripes_shift = -1; 165 else 166 sc->stripes_shift = __ffs(stripes); 167 168 ti->split_io = chunk_size; 169 ti->num_flush_requests = stripes; 170 ti->num_discard_requests = stripes; 171 172 sc->chunk_shift = ffs(chunk_size) - 1; 173 sc->chunk_mask = ((sector_t) chunk_size) - 1; 174 175 /* 176 * Get the stripe destinations. 177 */ 178 for (i = 0; i < stripes; i++) { 179 argv += 2; 180 181 r = get_stripe(ti, sc, i, argv); 182 if (r < 0) { 183 ti->error = "Couldn't parse stripe destination"; 184 while (i--) 185 dm_put_device(ti, sc->stripe[i].dev); 186 kfree(sc); 187 return r; 188 } 189 atomic_set(&(sc->stripe[i].error_count), 0); 190 } 191 192 ti->private = sc; 193 194 return 0; 195} 196 197static void stripe_dtr(struct dm_target *ti) 198{ 199 unsigned int i; 200 struct stripe_c *sc = (struct stripe_c *) ti->private; 201 202 for (i = 0; i < sc->stripes; i++) 203 dm_put_device(ti, sc->stripe[i].dev); 204 205 flush_work_sync(&sc->trigger_event); 206 kfree(sc); 207} 208 209static void stripe_map_sector(struct stripe_c *sc, sector_t sector, 210 uint32_t *stripe, sector_t *result) 211{ 212 sector_t offset = dm_target_offset(sc->ti, sector); 213 sector_t chunk = offset >> sc->chunk_shift; 214 215 if (sc->stripes_shift < 0) 216 *stripe = sector_div(chunk, sc->stripes); 217 else { 218 *stripe = chunk & (sc->stripes - 1); 219 chunk >>= sc->stripes_shift; 220 } 221 222 *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); 223} 224 225static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, 226 uint32_t target_stripe, sector_t *result) 227{ 228 uint32_t stripe; 229 230 stripe_map_sector(sc, sector, &stripe, result); 231 if (stripe == target_stripe) 232 return; 233 *result &= ~sc->chunk_mask; /* round down */ 234 if (target_stripe < stripe) 235 *result += sc->chunk_mask + 1; /* next chunk */ 236} 237 238static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, 239 uint32_t target_stripe) 240{ 241 sector_t begin, end; 242 243 stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin); 244 stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio), 245 target_stripe, &end); 246 if (begin < end) { 247 bio->bi_bdev = sc->stripe[target_stripe].dev->bdev; 248 bio->bi_sector = begin + sc->stripe[target_stripe].physical_start; 249 bio->bi_size = to_bytes(end - begin); 250 return DM_MAPIO_REMAPPED; 251 } else { 252 /* The range doesn't map to the target stripe */ 253 bio_endio(bio, 0); 254 return DM_MAPIO_SUBMITTED; 255 } 256} 257 258static int stripe_map(struct dm_target *ti, struct bio *bio, 259 union map_info *map_context) 260{ 261 struct stripe_c *sc = ti->private; 262 uint32_t stripe; 263 unsigned target_request_nr; 264 265 if (bio->bi_rw & REQ_FLUSH) { 266 target_request_nr = map_context->target_request_nr; 267 BUG_ON(target_request_nr >= sc->stripes); 268 bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; 269 return DM_MAPIO_REMAPPED; 270 } 271 if (unlikely(bio->bi_rw & REQ_DISCARD)) { 272 target_request_nr = map_context->target_request_nr; 273 BUG_ON(target_request_nr >= sc->stripes); 274 return stripe_map_discard(sc, bio, target_request_nr); 275 } 276 277 stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); 278 279 bio->bi_sector += sc->stripe[stripe].physical_start; 280 bio->bi_bdev = sc->stripe[stripe].dev->bdev; 281 282 return DM_MAPIO_REMAPPED; 283} 284 285/* 286 * Stripe status: 287 * 288 * INFO 289 * #stripes [stripe_name <stripe_name>] [group word count] 290 * [error count 'A|D' <error count 'A|D'>] 291 * 292 * TABLE 293 * #stripes [stripe chunk size] 294 * [stripe_name physical_start <stripe_name physical_start>] 295 * 296 */ 297 298static int stripe_status(struct dm_target *ti, 299 status_type_t type, char *result, unsigned int maxlen) 300{ 301 struct stripe_c *sc = (struct stripe_c *) ti->private; 302 char buffer[sc->stripes + 1]; 303 unsigned int sz = 0; 304 unsigned int i; 305 306 switch (type) { 307 case STATUSTYPE_INFO: 308 DMEMIT("%d ", sc->stripes); 309 for (i = 0; i < sc->stripes; i++) { 310 DMEMIT("%s ", sc->stripe[i].dev->name); 311 buffer[i] = atomic_read(&(sc->stripe[i].error_count)) ? 312 'D' : 'A'; 313 } 314 buffer[i] = '\0'; 315 DMEMIT("1 %s", buffer); 316 break; 317 318 case STATUSTYPE_TABLE: 319 DMEMIT("%d %llu", sc->stripes, 320 (unsigned long long)sc->chunk_mask + 1); 321 for (i = 0; i < sc->stripes; i++) 322 DMEMIT(" %s %llu", sc->stripe[i].dev->name, 323 (unsigned long long)sc->stripe[i].physical_start); 324 break; 325 } 326 return 0; 327} 328 329static int stripe_end_io(struct dm_target *ti, struct bio *bio, 330 int error, union map_info *map_context) 331{ 332 unsigned i; 333 char major_minor[16]; 334 struct stripe_c *sc = ti->private; 335 336 if (!error) 337 return 0; /* I/O complete */ 338 339 if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD)) 340 return error; 341 342 if (error == -EOPNOTSUPP) 343 return error; 344 345 memset(major_minor, 0, sizeof(major_minor)); 346 sprintf(major_minor, "%d:%d", 347 MAJOR(disk_devt(bio->bi_bdev->bd_disk)), 348 MINOR(disk_devt(bio->bi_bdev->bd_disk))); 349 350 /* 351 * Test to see which stripe drive triggered the event 352 * and increment error count for all stripes on that device. 353 * If the error count for a given device exceeds the threshold 354 * value we will no longer trigger any further events. 355 */ 356 for (i = 0; i < sc->stripes; i++) 357 if (!strcmp(sc->stripe[i].dev->name, major_minor)) { 358 atomic_inc(&(sc->stripe[i].error_count)); 359 if (atomic_read(&(sc->stripe[i].error_count)) < 360 DM_IO_ERROR_THRESHOLD) 361 schedule_work(&sc->trigger_event); 362 } 363 364 return error; 365} 366 367static int stripe_iterate_devices(struct dm_target *ti, 368 iterate_devices_callout_fn fn, void *data) 369{ 370 struct stripe_c *sc = ti->private; 371 int ret = 0; 372 unsigned i = 0; 373 374 do { 375 ret = fn(ti, sc->stripe[i].dev, 376 sc->stripe[i].physical_start, 377 sc->stripe_width, data); 378 } while (!ret && ++i < sc->stripes); 379 380 return ret; 381} 382 383static void stripe_io_hints(struct dm_target *ti, 384 struct queue_limits *limits) 385{ 386 struct stripe_c *sc = ti->private; 387 unsigned chunk_size = (sc->chunk_mask + 1) << 9; 388 389 blk_limits_io_min(limits, chunk_size); 390 blk_limits_io_opt(limits, chunk_size * sc->stripes); 391} 392 393static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm, 394 struct bio_vec *biovec, int max_size) 395{ 396 struct stripe_c *sc = ti->private; 397 sector_t bvm_sector = bvm->bi_sector; 398 uint32_t stripe; 399 struct request_queue *q; 400 401 stripe_map_sector(sc, bvm_sector, &stripe, &bvm_sector); 402 403 q = bdev_get_queue(sc->stripe[stripe].dev->bdev); 404 if (!q->merge_bvec_fn) 405 return max_size; 406 407 bvm->bi_bdev = sc->stripe[stripe].dev->bdev; 408 bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector; 409 410 return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); 411} 412 413static struct target_type stripe_target = { 414 .name = "striped", 415 .version = {1, 4, 0}, 416 .module = THIS_MODULE, 417 .ctr = stripe_ctr, 418 .dtr = stripe_dtr, 419 .map = stripe_map, 420 .end_io = stripe_end_io, 421 .status = stripe_status, 422 .iterate_devices = stripe_iterate_devices, 423 .io_hints = stripe_io_hints, 424 .merge = stripe_merge, 425}; 426 427int __init dm_stripe_init(void) 428{ 429 int r; 430 431 r = dm_register_target(&stripe_target); 432 if (r < 0) { 433 DMWARN("target registration failed"); 434 return r; 435 } 436 437 return r; 438} 439 440void dm_stripe_exit(void) 441{ 442 dm_unregister_target(&stripe_target); 443} 444