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