diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2009-04-08 19:27:12 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-04-08 19:27:12 -0400 |
commit | 9c47008d13add50ec4597a8b9eee200c515282c8 (patch) | |
tree | debd8ebb2fef2687d4548a177505ec30bda95503 /drivers/md | |
parent | 577c9c456f0e1371cbade38eaf91ae8e8a308555 (diff) |
dm: add integrity support
This patch provides support for data integrity passthrough in the device
mapper.
- If one or more component devices support integrity an integrity
profile is preallocated for the DM device.
- If all component devices have compatible profiles the DM device is
flagged as capable.
- Handle integrity metadata when splitting and cloning bios.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-ioctl.c | 21 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 40 | ||||
-rw-r--r-- | drivers/md/dm.c | 15 |
3 files changed, 76 insertions, 0 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index f01096549a93..823ceba6efa8 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -1047,6 +1047,19 @@ static int populate_table(struct dm_table *table, | |||
1047 | return dm_table_complete(table); | 1047 | return dm_table_complete(table); |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | static int table_prealloc_integrity(struct dm_table *t, | ||
1051 | struct mapped_device *md) | ||
1052 | { | ||
1053 | struct list_head *devices = dm_table_get_devices(t); | ||
1054 | struct dm_dev_internal *dd; | ||
1055 | |||
1056 | list_for_each_entry(dd, devices, list) | ||
1057 | if (bdev_get_integrity(dd->dm_dev.bdev)) | ||
1058 | return blk_integrity_register(dm_disk(md), NULL); | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1050 | static int table_load(struct dm_ioctl *param, size_t param_size) | 1063 | static int table_load(struct dm_ioctl *param, size_t param_size) |
1051 | { | 1064 | { |
1052 | int r; | 1065 | int r; |
@@ -1068,6 +1081,14 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1068 | goto out; | 1081 | goto out; |
1069 | } | 1082 | } |
1070 | 1083 | ||
1084 | r = table_prealloc_integrity(t, md); | ||
1085 | if (r) { | ||
1086 | DMERR("%s: could not register integrity profile.", | ||
1087 | dm_device_name(md)); | ||
1088 | dm_table_destroy(t); | ||
1089 | goto out; | ||
1090 | } | ||
1091 | |||
1071 | down_write(&_hash_lock); | 1092 | down_write(&_hash_lock); |
1072 | hc = dm_get_mdptr(md); | 1093 | hc = dm_get_mdptr(md); |
1073 | if (!hc || hc->md != md) { | 1094 | if (!hc || hc->md != md) { |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index e8361b191b9b..02d0b489fad6 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -879,6 +879,45 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) | |||
879 | return &t->targets[(KEYS_PER_NODE * n) + k]; | 879 | return &t->targets[(KEYS_PER_NODE * n) + k]; |
880 | } | 880 | } |
881 | 881 | ||
882 | /* | ||
883 | * Set the integrity profile for this device if all devices used have | ||
884 | * matching profiles. | ||
885 | */ | ||
886 | static void dm_table_set_integrity(struct dm_table *t) | ||
887 | { | ||
888 | struct list_head *devices = dm_table_get_devices(t); | ||
889 | struct dm_dev_internal *prev = NULL, *dd = NULL; | ||
890 | |||
891 | if (!blk_get_integrity(dm_disk(t->md))) | ||
892 | return; | ||
893 | |||
894 | list_for_each_entry(dd, devices, list) { | ||
895 | if (prev && | ||
896 | blk_integrity_compare(prev->dm_dev.bdev->bd_disk, | ||
897 | dd->dm_dev.bdev->bd_disk) < 0) { | ||
898 | DMWARN("%s: integrity not set: %s and %s mismatch", | ||
899 | dm_device_name(t->md), | ||
900 | prev->dm_dev.bdev->bd_disk->disk_name, | ||
901 | dd->dm_dev.bdev->bd_disk->disk_name); | ||
902 | goto no_integrity; | ||
903 | } | ||
904 | prev = dd; | ||
905 | } | ||
906 | |||
907 | if (!prev || !bdev_get_integrity(prev->dm_dev.bdev)) | ||
908 | goto no_integrity; | ||
909 | |||
910 | blk_integrity_register(dm_disk(t->md), | ||
911 | bdev_get_integrity(prev->dm_dev.bdev)); | ||
912 | |||
913 | return; | ||
914 | |||
915 | no_integrity: | ||
916 | blk_integrity_register(dm_disk(t->md), NULL); | ||
917 | |||
918 | return; | ||
919 | } | ||
920 | |||
882 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) | 921 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) |
883 | { | 922 | { |
884 | /* | 923 | /* |
@@ -899,6 +938,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) | |||
899 | else | 938 | else |
900 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); | 939 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); |
901 | 940 | ||
941 | dm_table_set_integrity(t); | ||
902 | } | 942 | } |
903 | 943 | ||
904 | unsigned int dm_table_get_num_targets(struct dm_table *t) | 944 | unsigned int dm_table_get_num_targets(struct dm_table *t) |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 788ba96a6256..25d86e2c01f2 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -700,6 +700,12 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, | |||
700 | clone->bi_io_vec->bv_len = clone->bi_size; | 700 | clone->bi_io_vec->bv_len = clone->bi_size; |
701 | clone->bi_flags |= 1 << BIO_CLONED; | 701 | clone->bi_flags |= 1 << BIO_CLONED; |
702 | 702 | ||
703 | if (bio_integrity(bio)) { | ||
704 | bio_integrity_clone(clone, bio, GFP_NOIO); | ||
705 | bio_integrity_trim(clone, | ||
706 | bio_sector_offset(bio, idx, offset), len); | ||
707 | } | ||
708 | |||
703 | return clone; | 709 | return clone; |
704 | } | 710 | } |
705 | 711 | ||
@@ -721,6 +727,14 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, | |||
721 | clone->bi_size = to_bytes(len); | 727 | clone->bi_size = to_bytes(len); |
722 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); | 728 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); |
723 | 729 | ||
730 | if (bio_integrity(bio)) { | ||
731 | bio_integrity_clone(clone, bio, GFP_NOIO); | ||
732 | |||
733 | if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) | ||
734 | bio_integrity_trim(clone, | ||
735 | bio_sector_offset(bio, idx, 0), len); | ||
736 | } | ||
737 | |||
724 | return clone; | 738 | return clone; |
725 | } | 739 | } |
726 | 740 | ||
@@ -1193,6 +1207,7 @@ static void free_dev(struct mapped_device *md) | |||
1193 | mempool_destroy(md->tio_pool); | 1207 | mempool_destroy(md->tio_pool); |
1194 | mempool_destroy(md->io_pool); | 1208 | mempool_destroy(md->io_pool); |
1195 | bioset_free(md->bs); | 1209 | bioset_free(md->bs); |
1210 | blk_integrity_unregister(md->disk); | ||
1196 | del_gendisk(md->disk); | 1211 | del_gendisk(md->disk); |
1197 | free_minor(minor); | 1212 | free_minor(minor); |
1198 | 1213 | ||