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.c60
1 files changed, 32 insertions, 28 deletions
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index c35890990985..3535c23af288 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -146,7 +146,7 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev)
146 int i; 146 int i;
147 147
148 seq_printf (seq, " [%d/%d] [", conf->raid_disks, 148 seq_printf (seq, " [%d/%d] [", conf->raid_disks,
149 conf->working_disks); 149 conf->raid_disks - mddev->degraded);
150 for (i = 0; i < conf->raid_disks; i++) 150 for (i = 0; i < conf->raid_disks; i++)
151 seq_printf (seq, "%s", 151 seq_printf (seq, "%s",
152 conf->multipaths[i].rdev && 152 conf->multipaths[i].rdev &&
@@ -186,35 +186,36 @@ static int multipath_congested(void *data, int bits)
186static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) 186static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
187{ 187{
188 multipath_conf_t *conf = mddev->private; 188 multipath_conf_t *conf = mddev->private;
189 char b[BDEVNAME_SIZE];
189 190
190 if (conf->working_disks <= 1) { 191 if (conf->raid_disks - mddev->degraded <= 1) {
191 /* 192 /*
192 * 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
193 * first check if this is a queued request for a device 194 * first check if this is a queued request for a device
194 * which has just failed. 195 * which has just failed.
195 */ 196 */
196 printk(KERN_ALERT 197 printk(KERN_ALERT
197 "multipath: only one IO path left and IO error.\n"); 198 "multipath: only one IO path left and IO error.\n");
198 /* leave it active... it's all we have */ 199 /* leave it active... it's all we have */
199 } else { 200 return;
200 /* 201 }
201 * Mark disk as unusable 202 /*
202 */ 203 * Mark disk as unusable
203 if (!test_bit(Faulty, &rdev->flags)) { 204 */
204 char b[BDEVNAME_SIZE]; 205 if (test_and_clear_bit(In_sync, &rdev->flags)) {
205 clear_bit(In_sync, &rdev->flags); 206 unsigned long flags;
206 set_bit(Faulty, &rdev->flags); 207 spin_lock_irqsave(&conf->device_lock, flags);
207 set_bit(MD_CHANGE_DEVS, &mddev->flags); 208 mddev->degraded++;
208 conf->working_disks--; 209 spin_unlock_irqrestore(&conf->device_lock, flags);
209 mddev->degraded++;
210 printk(KERN_ALERT "multipath: IO failure on %s,"
211 " disabling IO path.\n"
212 "multipath: Operation continuing"
213 " on %d IO paths.\n",
214 bdevname (rdev->bdev,b),
215 conf->working_disks);
216 }
217 } 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);
218} 219}
219 220
220static void print_multipath_conf (multipath_conf_t *conf) 221static void print_multipath_conf (multipath_conf_t *conf)
@@ -227,7 +228,7 @@ static void print_multipath_conf (multipath_conf_t *conf)
227 printk("(conf==NULL)\n"); 228 printk("(conf==NULL)\n");
228 return; 229 return;
229 } 230 }
230 printk(" --- wd:%d rd:%d\n", conf->working_disks, 231 printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
231 conf->raid_disks); 232 conf->raid_disks);
232 233
233 for (i = 0; i < conf->raid_disks; i++) { 234 for (i = 0; i < conf->raid_disks; i++) {
@@ -274,10 +275,11 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
274 PAGE_CACHE_SIZE - 1); 275 PAGE_CACHE_SIZE - 1);
275 } 276 }
276 277
277 conf->working_disks++; 278 spin_lock_irq(&conf->device_lock);
278 mddev->degraded--; 279 mddev->degraded--;
279 rdev->raid_disk = path; 280 rdev->raid_disk = path;
280 set_bit(In_sync, &rdev->flags); 281 set_bit(In_sync, &rdev->flags);
282 spin_unlock_irq(&conf->device_lock);
281 rcu_assign_pointer(p->rdev, rdev); 283 rcu_assign_pointer(p->rdev, rdev);
282 err = 0; 284 err = 0;
283 md_integrity_add_rdev(rdev, mddev); 285 md_integrity_add_rdev(rdev, mddev);
@@ -391,6 +393,7 @@ static int multipath_run (mddev_t *mddev)
391 int disk_idx; 393 int disk_idx;
392 struct multipath_info *disk; 394 struct multipath_info *disk;
393 mdk_rdev_t *rdev; 395 mdk_rdev_t *rdev;
396 int working_disks;
394 397
395 if (md_check_no_bitmap(mddev)) 398 if (md_check_no_bitmap(mddev))
396 return -EINVAL; 399 return -EINVAL;
@@ -424,7 +427,7 @@ static int multipath_run (mddev_t *mddev)
424 goto out_free_conf; 427 goto out_free_conf;
425 } 428 }
426 429
427 conf->working_disks = 0; 430 working_disks = 0;
428 list_for_each_entry(rdev, &mddev->disks, same_set) { 431 list_for_each_entry(rdev, &mddev->disks, same_set) {
429 disk_idx = rdev->raid_disk; 432 disk_idx = rdev->raid_disk;
430 if (disk_idx < 0 || 433 if (disk_idx < 0 ||
@@ -446,7 +449,7 @@ static int multipath_run (mddev_t *mddev)
446 } 449 }
447 450
448 if (!test_bit(Faulty, &rdev->flags)) 451 if (!test_bit(Faulty, &rdev->flags))
449 conf->working_disks++; 452 working_disks++;
450 } 453 }
451 454
452 conf->raid_disks = mddev->raid_disks; 455 conf->raid_disks = mddev->raid_disks;
@@ -454,12 +457,12 @@ static int multipath_run (mddev_t *mddev)
454 spin_lock_init(&conf->device_lock); 457 spin_lock_init(&conf->device_lock);
455 INIT_LIST_HEAD(&conf->retry_list); 458 INIT_LIST_HEAD(&conf->retry_list);
456 459
457 if (!conf->working_disks) { 460 if (!working_disks) {
458 printk(KERN_ERR "multipath: no operational IO paths for %s\n", 461 printk(KERN_ERR "multipath: no operational IO paths for %s\n",
459 mdname(mddev)); 462 mdname(mddev));
460 goto out_free_conf; 463 goto out_free_conf;
461 } 464 }
462 mddev->degraded = conf->raid_disks - conf->working_disks; 465 mddev->degraded = conf->raid_disks - working_disks;
463 466
464 conf->pool = mempool_create_kmalloc_pool(NR_RESERVED_BUFS, 467 conf->pool = mempool_create_kmalloc_pool(NR_RESERVED_BUFS,
465 sizeof(struct multipath_bh)); 468 sizeof(struct multipath_bh));
@@ -481,7 +484,8 @@ static int multipath_run (mddev_t *mddev)
481 484
482 printk(KERN_INFO 485 printk(KERN_INFO
483 "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",
484 mdname(mddev), conf->working_disks, mddev->raid_disks); 487 mdname(mddev), conf->raid_disks - mddev->degraded,
488 mddev->raid_disks);
485 /* 489 /*
486 * Ok, everything is just fine now 490 * Ok, everything is just fine now
487 */ 491 */