aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorAndre Noll <maan@systemlinux.org>2009-08-02 20:59:47 -0400
committerNeilBrown <neilb@suse.de>2009-08-02 20:59:47 -0400
commitac5e7113e74872928844d00085bd47c988f12728 (patch)
treedabce6a99c2af9f00b33660f6b2d906cce836764 /drivers/md
parent95fc17aac45300f45968aacd97a536ddd8db8101 (diff)
md: Push down data integrity code to personalities.
This patch replaces md_integrity_check() by two new public functions: md_integrity_register() and md_integrity_add_rdev() which are both personality-independent. md_integrity_register() is called from the ->run and ->hot_remove methods of all personalities that support data integrity. The function iterates over the component devices of the array and determines if all active devices are integrity capable and if their profiles match. If this is the case, the common profile is registered for the mddev via blk_integrity_register(). The second new function, md_integrity_add_rdev() is called from the ->hot_add_disk methods, i.e. whenever a new device is being added to a raid array. If the new device does not support data integrity, or has a profile different from the one already registered, data integrity for the mddev is disabled. For raid0 and linear, only the call to md_integrity_register() from the ->run method is necessary. Signed-off-by: Andre Noll <maan@systemlinux.org> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/linear.c1
-rw-r--r--drivers/md/md.c94
-rw-r--r--drivers/md/md.h2
-rw-r--r--drivers/md/multipath.c5
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c4
7 files changed, 80 insertions, 33 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 5810fa906af0..54c8677f1e59 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -220,6 +220,7 @@ static int linear_run (mddev_t *mddev)
220 mddev->queue->unplug_fn = linear_unplug; 220 mddev->queue->unplug_fn = linear_unplug;
221 mddev->queue->backing_dev_info.congested_fn = linear_congested; 221 mddev->queue->backing_dev_info.congested_fn = linear_congested;
222 mddev->queue->backing_dev_info.congested_data = mddev; 222 mddev->queue->backing_dev_info.congested_data = mddev;
223 md_integrity_register(mddev);
223 return 0; 224 return 0;
224} 225}
225 226
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d4351ff0849f..180949e94a7b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1487,37 +1487,76 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
1487 1487
1488static LIST_HEAD(pending_raid_disks); 1488static LIST_HEAD(pending_raid_disks);
1489 1489
1490static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev) 1490/*
1491 * Try to register data integrity profile for an mddev
1492 *
1493 * This is called when an array is started and after a disk has been kicked
1494 * from the array. It only succeeds if all working and active component devices
1495 * are integrity capable with matching profiles.
1496 */
1497int md_integrity_register(mddev_t *mddev)
1498{
1499 mdk_rdev_t *rdev, *reference = NULL;
1500
1501 if (list_empty(&mddev->disks))
1502 return 0; /* nothing to do */
1503 if (blk_get_integrity(mddev->gendisk))
1504 return 0; /* already registered */
1505 list_for_each_entry(rdev, &mddev->disks, same_set) {
1506 /* skip spares and non-functional disks */
1507 if (test_bit(Faulty, &rdev->flags))
1508 continue;
1509 if (rdev->raid_disk < 0)
1510 continue;
1511 /*
1512 * If at least one rdev is not integrity capable, we can not
1513 * enable data integrity for the md device.
1514 */
1515 if (!bdev_get_integrity(rdev->bdev))
1516 return -EINVAL;
1517 if (!reference) {
1518 /* Use the first rdev as the reference */
1519 reference = rdev;
1520 continue;
1521 }
1522 /* does this rdev's profile match the reference profile? */
1523 if (blk_integrity_compare(reference->bdev->bd_disk,
1524 rdev->bdev->bd_disk) < 0)
1525 return -EINVAL;
1526 }
1527 /*
1528 * All component devices are integrity capable and have matching
1529 * profiles, register the common profile for the md device.
1530 */
1531 if (blk_integrity_register(mddev->gendisk,
1532 bdev_get_integrity(reference->bdev)) != 0) {
1533 printk(KERN_ERR "md: failed to register integrity for %s\n",
1534 mdname(mddev));
1535 return -EINVAL;
1536 }
1537 printk(KERN_NOTICE "md: data integrity on %s enabled\n",
1538 mdname(mddev));
1539 return 0;
1540}
1541EXPORT_SYMBOL(md_integrity_register);
1542
1543/* Disable data integrity if non-capable/non-matching disk is being added */
1544void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
1491{ 1545{
1492 struct mdk_personality *pers = mddev->pers;
1493 struct gendisk *disk = mddev->gendisk;
1494 struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev); 1546 struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
1495 struct blk_integrity *bi_mddev = blk_get_integrity(disk); 1547 struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
1496 1548
1497 /* Data integrity passthrough not supported on RAID 4, 5 and 6 */ 1549 if (!bi_mddev) /* nothing to do */
1498 if (pers && pers->level >= 4 && pers->level <= 6)
1499 return; 1550 return;
1500 1551 if (rdev->raid_disk < 0) /* skip spares */
1501 /* If rdev is integrity capable, register profile for mddev */
1502 if (!bi_mddev && bi_rdev) {
1503 if (blk_integrity_register(disk, bi_rdev))
1504 printk(KERN_ERR "%s: %s Could not register integrity!\n",
1505 __func__, disk->disk_name);
1506 else
1507 printk(KERN_NOTICE "Enabling data integrity on %s\n",
1508 disk->disk_name);
1509 return; 1552 return;
1510 } 1553 if (bi_rdev && blk_integrity_compare(mddev->gendisk,
1511 1554 rdev->bdev->bd_disk) >= 0)
1512 /* Check that mddev and rdev have matching profiles */ 1555 return;
1513 if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) { 1556 printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
1514 printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__, 1557 blk_integrity_unregister(mddev->gendisk);
1515 disk->disk_name, rdev->bdev->bd_disk->disk_name);
1516 printk(KERN_NOTICE "Disabling data integrity on %s\n",
1517 disk->disk_name);
1518 blk_integrity_unregister(disk);
1519 }
1520} 1558}
1559EXPORT_SYMBOL(md_integrity_add_rdev);
1521 1560
1522static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) 1561static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
1523{ 1562{
@@ -1591,7 +1630,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
1591 /* May as well allow recovery to be retried once */ 1630 /* May as well allow recovery to be retried once */
1592 mddev->recovery_disabled = 0; 1631 mddev->recovery_disabled = 0;
1593 1632
1594 md_integrity_check(rdev, mddev);
1595 return 0; 1633 return 0;
1596 1634
1597 fail: 1635 fail:
@@ -4048,10 +4086,6 @@ static int do_md_run(mddev_t * mddev)
4048 } 4086 }
4049 strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); 4087 strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
4050 4088
4051 if (pers->level >= 4 && pers->level <= 6)
4052 /* Cannot support integrity (yet) */
4053 blk_integrity_unregister(mddev->gendisk);
4054
4055 if (mddev->reshape_position != MaxSector && 4089 if (mddev->reshape_position != MaxSector &&
4056 pers->start_reshape == NULL) { 4090 pers->start_reshape == NULL) {
4057 /* This personality cannot handle reshaping... */ 4091 /* This personality cannot handle reshaping... */
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 9430a110db93..78f03168baf9 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -431,5 +431,7 @@ extern int md_allow_write(mddev_t *mddev);
431extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); 431extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
432extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); 432extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
433extern int md_check_no_bitmap(mddev_t *mddev); 433extern int md_check_no_bitmap(mddev_t *mddev);
434extern int md_integrity_register(mddev_t *mddev);
435void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
434 436
435#endif /* _MD_MD_H */ 437#endif /* _MD_MD_H */
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 237fe3fd235c..7140909f6662 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -313,6 +313,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
313 set_bit(In_sync, &rdev->flags); 313 set_bit(In_sync, &rdev->flags);
314 rcu_assign_pointer(p->rdev, rdev); 314 rcu_assign_pointer(p->rdev, rdev);
315 err = 0; 315 err = 0;
316 md_integrity_add_rdev(rdev, mddev);
316 break; 317 break;
317 } 318 }
318 319
@@ -345,7 +346,9 @@ static int multipath_remove_disk(mddev_t *mddev, int number)
345 /* lost the race, try later */ 346 /* lost the race, try later */
346 err = -EBUSY; 347 err = -EBUSY;
347 p->rdev = rdev; 348 p->rdev = rdev;
349 goto abort;
348 } 350 }
351 md_integrity_register(mddev);
349 } 352 }
350abort: 353abort:
351 354
@@ -519,7 +522,7 @@ static int multipath_run (mddev_t *mddev)
519 mddev->queue->unplug_fn = multipath_unplug; 522 mddev->queue->unplug_fn = multipath_unplug;
520 mddev->queue->backing_dev_info.congested_fn = multipath_congested; 523 mddev->queue->backing_dev_info.congested_fn = multipath_congested;
521 mddev->queue->backing_dev_info.congested_data = mddev; 524 mddev->queue->backing_dev_info.congested_data = mddev;
522 525 md_integrity_register(mddev);
523 return 0; 526 return 0;
524 527
525out_free_conf: 528out_free_conf:
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 335f490dcad6..898e2bdfee47 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -351,6 +351,7 @@ static int raid0_run(mddev_t *mddev)
351 351
352 blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec); 352 blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
353 dump_zones(mddev); 353 dump_zones(mddev);
354 md_integrity_register(mddev);
354 return 0; 355 return 0;
355} 356}
356 357
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 0569efba0c02..67e794d0097f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1144,7 +1144,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
1144 rcu_assign_pointer(p->rdev, rdev); 1144 rcu_assign_pointer(p->rdev, rdev);
1145 break; 1145 break;
1146 } 1146 }
1147 1147 md_integrity_add_rdev(rdev, mddev);
1148 print_conf(conf); 1148 print_conf(conf);
1149 return err; 1149 return err;
1150} 1150}
@@ -1178,7 +1178,9 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
1178 /* lost the race, try later */ 1178 /* lost the race, try later */
1179 err = -EBUSY; 1179 err = -EBUSY;
1180 p->rdev = rdev; 1180 p->rdev = rdev;
1181 goto abort;
1181 } 1182 }
1183 md_integrity_register(mddev);
1182 } 1184 }
1183abort: 1185abort:
1184 1186
@@ -2067,7 +2069,7 @@ static int run(mddev_t *mddev)
2067 mddev->queue->unplug_fn = raid1_unplug; 2069 mddev->queue->unplug_fn = raid1_unplug;
2068 mddev->queue->backing_dev_info.congested_fn = raid1_congested; 2070 mddev->queue->backing_dev_info.congested_fn = raid1_congested;
2069 mddev->queue->backing_dev_info.congested_data = mddev; 2071 mddev->queue->backing_dev_info.congested_data = mddev;
2070 2072 md_integrity_register(mddev);
2071 return 0; 2073 return 0;
2072 2074
2073out_no_mem: 2075out_no_mem:
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7298a5e5a183..3d9020cf6f6e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1170,6 +1170,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
1170 break; 1170 break;
1171 } 1171 }
1172 1172
1173 md_integrity_add_rdev(rdev, mddev);
1173 print_conf(conf); 1174 print_conf(conf);
1174 return err; 1175 return err;
1175} 1176}
@@ -1203,7 +1204,9 @@ static int raid10_remove_disk(mddev_t *mddev, int number)
1203 /* lost the race, try later */ 1204 /* lost the race, try later */
1204 err = -EBUSY; 1205 err = -EBUSY;
1205 p->rdev = rdev; 1206 p->rdev = rdev;
1207 goto abort;
1206 } 1208 }
1209 md_integrity_register(mddev);
1207 } 1210 }
1208abort: 1211abort:
1209 1212
@@ -2225,6 +2228,7 @@ static int run(mddev_t *mddev)
2225 2228
2226 if (conf->near_copies < mddev->raid_disks) 2229 if (conf->near_copies < mddev->raid_disks)
2227 blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); 2230 blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
2231 md_integrity_register(mddev);
2228 return 0; 2232 return 0;
2229 2233
2230out_free_conf: 2234out_free_conf: