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