diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/md/multipath.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/md/multipath.c')
-rw-r--r-- | drivers/md/multipath.c | 103 |
1 files changed, 39 insertions, 64 deletions
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 0307d217e7a4..3535c23af288 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -106,44 +106,14 @@ static void multipath_end_request(struct bio *bio, int error) | |||
106 | rdev_dec_pending(rdev, conf->mddev); | 106 | rdev_dec_pending(rdev, conf->mddev); |
107 | } | 107 | } |
108 | 108 | ||
109 | static void unplug_slaves(mddev_t *mddev) | ||
110 | { | ||
111 | multipath_conf_t *conf = mddev->private; | ||
112 | int i; | ||
113 | |||
114 | rcu_read_lock(); | ||
115 | for (i=0; i<mddev->raid_disks; i++) { | ||
116 | mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); | ||
117 | if (rdev && !test_bit(Faulty, &rdev->flags) | ||
118 | && atomic_read(&rdev->nr_pending)) { | ||
119 | struct request_queue *r_queue = bdev_get_queue(rdev->bdev); | ||
120 | |||
121 | atomic_inc(&rdev->nr_pending); | ||
122 | rcu_read_unlock(); | ||
123 | |||
124 | blk_unplug(r_queue); | ||
125 | |||
126 | rdev_dec_pending(rdev, mddev); | ||
127 | rcu_read_lock(); | ||
128 | } | ||
129 | } | ||
130 | rcu_read_unlock(); | ||
131 | } | ||
132 | |||
133 | static void multipath_unplug(struct request_queue *q) | ||
134 | { | ||
135 | unplug_slaves(q->queuedata); | ||
136 | } | ||
137 | |||
138 | |||
139 | static int multipath_make_request(mddev_t *mddev, struct bio * bio) | 109 | static int multipath_make_request(mddev_t *mddev, struct bio * bio) |
140 | { | 110 | { |
141 | multipath_conf_t *conf = mddev->private; | 111 | multipath_conf_t *conf = mddev->private; |
142 | struct multipath_bh * mp_bh; | 112 | struct multipath_bh * mp_bh; |
143 | struct multipath_info *multipath; | 113 | struct multipath_info *multipath; |
144 | 114 | ||
145 | if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { | 115 | if (unlikely(bio->bi_rw & REQ_FLUSH)) { |
146 | md_barrier_request(mddev, bio); | 116 | md_flush_request(mddev, bio); |
147 | return 0; | 117 | return 0; |
148 | } | 118 | } |
149 | 119 | ||
@@ -176,7 +146,7 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) | |||
176 | int i; | 146 | int i; |
177 | 147 | ||
178 | seq_printf (seq, " [%d/%d] [", conf->raid_disks, | 148 | seq_printf (seq, " [%d/%d] [", conf->raid_disks, |
179 | conf->working_disks); | 149 | conf->raid_disks - mddev->degraded); |
180 | for (i = 0; i < conf->raid_disks; i++) | 150 | for (i = 0; i < conf->raid_disks; i++) |
181 | seq_printf (seq, "%s", | 151 | seq_printf (seq, "%s", |
182 | conf->multipaths[i].rdev && | 152 | conf->multipaths[i].rdev && |
@@ -216,35 +186,36 @@ static int multipath_congested(void *data, int bits) | |||
216 | static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) | 186 | static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) |
217 | { | 187 | { |
218 | multipath_conf_t *conf = mddev->private; | 188 | multipath_conf_t *conf = mddev->private; |
189 | char b[BDEVNAME_SIZE]; | ||
219 | 190 | ||
220 | if (conf->working_disks <= 1) { | 191 | if (conf->raid_disks - mddev->degraded <= 1) { |
221 | /* | 192 | /* |
222 | * Uh oh, we can do nothing if this is our last path, but | 193 | * Uh oh, we can do nothing if this is our last path, but |
223 | * first check if this is a queued request for a device | 194 | * first check if this is a queued request for a device |
224 | * which has just failed. | 195 | * which has just failed. |
225 | */ | 196 | */ |
226 | printk(KERN_ALERT | 197 | printk(KERN_ALERT |
227 | "multipath: only one IO path left and IO error.\n"); | 198 | "multipath: only one IO path left and IO error.\n"); |
228 | /* leave it active... it's all we have */ | 199 | /* leave it active... it's all we have */ |
229 | } else { | 200 | return; |
230 | /* | ||
231 | * Mark disk as unusable | ||
232 | */ | ||
233 | if (!test_bit(Faulty, &rdev->flags)) { | ||
234 | char b[BDEVNAME_SIZE]; | ||
235 | clear_bit(In_sync, &rdev->flags); | ||
236 | set_bit(Faulty, &rdev->flags); | ||
237 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
238 | conf->working_disks--; | ||
239 | mddev->degraded++; | ||
240 | printk(KERN_ALERT "multipath: IO failure on %s," | ||
241 | " disabling IO path.\n" | ||
242 | "multipath: Operation continuing" | ||
243 | " on %d IO paths.\n", | ||
244 | bdevname (rdev->bdev,b), | ||
245 | conf->working_disks); | ||
246 | } | ||
247 | } | 201 | } |
202 | /* | ||
203 | * Mark disk as unusable | ||
204 | */ | ||
205 | if (test_and_clear_bit(In_sync, &rdev->flags)) { | ||
206 | unsigned long flags; | ||
207 | spin_lock_irqsave(&conf->device_lock, flags); | ||
208 | mddev->degraded++; | ||
209 | spin_unlock_irqrestore(&conf->device_lock, flags); | ||
210 | } | ||
211 | set_bit(Faulty, &rdev->flags); | ||
212 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
213 | printk(KERN_ALERT "multipath: IO failure on %s," | ||
214 | " disabling IO path.\n" | ||
215 | "multipath: Operation continuing" | ||
216 | " on %d IO paths.\n", | ||
217 | bdevname(rdev->bdev, b), | ||
218 | conf->raid_disks - mddev->degraded); | ||
248 | } | 219 | } |
249 | 220 | ||
250 | static void print_multipath_conf (multipath_conf_t *conf) | 221 | static void print_multipath_conf (multipath_conf_t *conf) |
@@ -257,7 +228,7 @@ static void print_multipath_conf (multipath_conf_t *conf) | |||
257 | printk("(conf==NULL)\n"); | 228 | printk("(conf==NULL)\n"); |
258 | return; | 229 | return; |
259 | } | 230 | } |
260 | printk(" --- wd:%d rd:%d\n", conf->working_disks, | 231 | printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded, |
261 | conf->raid_disks); | 232 | conf->raid_disks); |
262 | 233 | ||
263 | for (i = 0; i < conf->raid_disks; i++) { | 234 | for (i = 0; i < conf->raid_disks; i++) { |
@@ -304,10 +275,11 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
304 | PAGE_CACHE_SIZE - 1); | 275 | PAGE_CACHE_SIZE - 1); |
305 | } | 276 | } |
306 | 277 | ||
307 | conf->working_disks++; | 278 | spin_lock_irq(&conf->device_lock); |
308 | mddev->degraded--; | 279 | mddev->degraded--; |
309 | rdev->raid_disk = path; | 280 | rdev->raid_disk = path; |
310 | set_bit(In_sync, &rdev->flags); | 281 | set_bit(In_sync, &rdev->flags); |
282 | spin_unlock_irq(&conf->device_lock); | ||
311 | rcu_assign_pointer(p->rdev, rdev); | 283 | rcu_assign_pointer(p->rdev, rdev); |
312 | err = 0; | 284 | err = 0; |
313 | md_integrity_add_rdev(rdev, mddev); | 285 | md_integrity_add_rdev(rdev, mddev); |
@@ -345,7 +317,7 @@ static int multipath_remove_disk(mddev_t *mddev, int number) | |||
345 | p->rdev = rdev; | 317 | p->rdev = rdev; |
346 | goto abort; | 318 | goto abort; |
347 | } | 319 | } |
348 | md_integrity_register(mddev); | 320 | err = md_integrity_register(mddev); |
349 | } | 321 | } |
350 | abort: | 322 | abort: |
351 | 323 | ||
@@ -421,6 +393,7 @@ static int multipath_run (mddev_t *mddev) | |||
421 | int disk_idx; | 393 | int disk_idx; |
422 | struct multipath_info *disk; | 394 | struct multipath_info *disk; |
423 | mdk_rdev_t *rdev; | 395 | mdk_rdev_t *rdev; |
396 | int working_disks; | ||
424 | 397 | ||
425 | if (md_check_no_bitmap(mddev)) | 398 | if (md_check_no_bitmap(mddev)) |
426 | return -EINVAL; | 399 | return -EINVAL; |
@@ -435,7 +408,6 @@ static int multipath_run (mddev_t *mddev) | |||
435 | * bookkeeping area. [whatever we allocate in multipath_run(), | 408 | * bookkeeping area. [whatever we allocate in multipath_run(), |
436 | * should be freed in multipath_stop()] | 409 | * should be freed in multipath_stop()] |
437 | */ | 410 | */ |
438 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; | ||
439 | 411 | ||
440 | conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); | 412 | conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); |
441 | mddev->private = conf; | 413 | mddev->private = conf; |
@@ -455,7 +427,7 @@ static int multipath_run (mddev_t *mddev) | |||
455 | goto out_free_conf; | 427 | goto out_free_conf; |
456 | } | 428 | } |
457 | 429 | ||
458 | conf->working_disks = 0; | 430 | working_disks = 0; |
459 | list_for_each_entry(rdev, &mddev->disks, same_set) { | 431 | list_for_each_entry(rdev, &mddev->disks, same_set) { |
460 | disk_idx = rdev->raid_disk; | 432 | disk_idx = rdev->raid_disk; |
461 | if (disk_idx < 0 || | 433 | if (disk_idx < 0 || |
@@ -477,7 +449,7 @@ static int multipath_run (mddev_t *mddev) | |||
477 | } | 449 | } |
478 | 450 | ||
479 | if (!test_bit(Faulty, &rdev->flags)) | 451 | if (!test_bit(Faulty, &rdev->flags)) |
480 | conf->working_disks++; | 452 | working_disks++; |
481 | } | 453 | } |
482 | 454 | ||
483 | conf->raid_disks = mddev->raid_disks; | 455 | conf->raid_disks = mddev->raid_disks; |
@@ -485,12 +457,12 @@ static int multipath_run (mddev_t *mddev) | |||
485 | spin_lock_init(&conf->device_lock); | 457 | spin_lock_init(&conf->device_lock); |
486 | INIT_LIST_HEAD(&conf->retry_list); | 458 | INIT_LIST_HEAD(&conf->retry_list); |
487 | 459 | ||
488 | if (!conf->working_disks) { | 460 | if (!working_disks) { |
489 | printk(KERN_ERR "multipath: no operational IO paths for %s\n", | 461 | printk(KERN_ERR "multipath: no operational IO paths for %s\n", |
490 | mdname(mddev)); | 462 | mdname(mddev)); |
491 | goto out_free_conf; | 463 | goto out_free_conf; |
492 | } | 464 | } |
493 | mddev->degraded = conf->raid_disks - conf->working_disks; | 465 | mddev->degraded = conf->raid_disks - working_disks; |
494 | 466 | ||
495 | conf->pool = mempool_create_kmalloc_pool(NR_RESERVED_BUFS, | 467 | conf->pool = mempool_create_kmalloc_pool(NR_RESERVED_BUFS, |
496 | sizeof(struct multipath_bh)); | 468 | sizeof(struct multipath_bh)); |
@@ -512,16 +484,19 @@ static int multipath_run (mddev_t *mddev) | |||
512 | 484 | ||
513 | printk(KERN_INFO | 485 | printk(KERN_INFO |
514 | "multipath: array %s active with %d out of %d IO paths\n", | 486 | "multipath: array %s active with %d out of %d IO paths\n", |
515 | mdname(mddev), conf->working_disks, mddev->raid_disks); | 487 | mdname(mddev), conf->raid_disks - mddev->degraded, |
488 | mddev->raid_disks); | ||
516 | /* | 489 | /* |
517 | * Ok, everything is just fine now | 490 | * Ok, everything is just fine now |
518 | */ | 491 | */ |
519 | md_set_array_sectors(mddev, multipath_size(mddev, 0, 0)); | 492 | md_set_array_sectors(mddev, multipath_size(mddev, 0, 0)); |
520 | 493 | ||
521 | mddev->queue->unplug_fn = multipath_unplug; | ||
522 | mddev->queue->backing_dev_info.congested_fn = multipath_congested; | 494 | mddev->queue->backing_dev_info.congested_fn = multipath_congested; |
523 | mddev->queue->backing_dev_info.congested_data = mddev; | 495 | mddev->queue->backing_dev_info.congested_data = mddev; |
524 | md_integrity_register(mddev); | 496 | |
497 | if (md_integrity_register(mddev)) | ||
498 | goto out_free_conf; | ||
499 | |||
525 | return 0; | 500 | return 0; |
526 | 501 | ||
527 | out_free_conf: | 502 | out_free_conf: |