aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/multipath.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/multipath.c')
-rw-r--r--drivers/md/multipath.c103
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
109static 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
133static void multipath_unplug(struct request_queue *q)
134{
135 unplug_slaves(q->queuedata);
136}
137
138
139static int multipath_make_request(mddev_t *mddev, struct bio * bio) 109static 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)
216static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) 186static 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
250static void print_multipath_conf (multipath_conf_t *conf) 221static 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 }
350abort: 322abort:
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
527out_free_conf: 502out_free_conf: