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