diff options
-rw-r--r-- | drivers/md/linear.c | 1 | ||||
-rw-r--r-- | drivers/md/md.c | 94 | ||||
-rw-r--r-- | drivers/md/md.h | 2 | ||||
-rw-r--r-- | drivers/md/multipath.c | 5 | ||||
-rw-r--r-- | drivers/md/raid0.c | 1 | ||||
-rw-r--r-- | drivers/md/raid1.c | 6 | ||||
-rw-r--r-- | drivers/md/raid10.c | 4 |
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 | ||
1488 | static LIST_HEAD(pending_raid_disks); | 1488 | static LIST_HEAD(pending_raid_disks); |
1489 | 1489 | ||
1490 | static 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 | */ | ||
1497 | int 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 | } | ||
1541 | EXPORT_SYMBOL(md_integrity_register); | ||
1542 | |||
1543 | /* Disable data integrity if non-capable/non-matching disk is being added */ | ||
1544 | void 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 | } |
1559 | EXPORT_SYMBOL(md_integrity_add_rdev); | ||
1521 | 1560 | ||
1522 | static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | 1561 | static 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); | |||
431 | extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); | 431 | extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); |
432 | extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); | 432 | extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); |
433 | extern int md_check_no_bitmap(mddev_t *mddev); | 433 | extern int md_check_no_bitmap(mddev_t *mddev); |
434 | extern int md_integrity_register(mddev_t *mddev); | ||
435 | void 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 | } |
350 | abort: | 353 | abort: |
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 | ||
525 | out_free_conf: | 528 | out_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 | } |
1183 | abort: | 1185 | abort: |
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 | ||
2073 | out_no_mem: | 2075 | out_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 | } |
1208 | abort: | 1211 | abort: |
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 | ||
2230 | out_free_conf: | 2234 | out_free_conf: |