diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2008-06-30 14:04:41 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-07-03 07:21:13 -0400 |
commit | 7ba1ba12eeef0aa7113beb16410ef8b7c748e18b (patch) | |
tree | 4629aabe88bf095d58eabd2f451207695bb35b08 /include/linux/blkdev.h | |
parent | 51d654e1d885607a6edd02b337105fa5c28b6d33 (diff) |
block: Block layer data integrity support
Some block devices support verifying the integrity of requests by way
of checksums or other protection information that is submitted along
with the I/O.
This patch implements support for generating and verifying integrity
metadata, as well as correctly merging, splitting and cloning bios and
requests that have this extra information attached.
See Documentation/block/data-integrity.txt for more information.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'include/linux/blkdev.h')
-rw-r--r-- | include/linux/blkdev.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6a3da6717135..4a9ed45270ff 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -112,6 +112,7 @@ enum rq_flag_bits { | |||
112 | __REQ_ALLOCED, /* request came from our alloc pool */ | 112 | __REQ_ALLOCED, /* request came from our alloc pool */ |
113 | __REQ_RW_META, /* metadata io request */ | 113 | __REQ_RW_META, /* metadata io request */ |
114 | __REQ_COPY_USER, /* contains copies of user pages */ | 114 | __REQ_COPY_USER, /* contains copies of user pages */ |
115 | __REQ_INTEGRITY, /* integrity metadata has been remapped */ | ||
115 | __REQ_NR_BITS, /* stops here */ | 116 | __REQ_NR_BITS, /* stops here */ |
116 | }; | 117 | }; |
117 | 118 | ||
@@ -134,6 +135,7 @@ enum rq_flag_bits { | |||
134 | #define REQ_ALLOCED (1 << __REQ_ALLOCED) | 135 | #define REQ_ALLOCED (1 << __REQ_ALLOCED) |
135 | #define REQ_RW_META (1 << __REQ_RW_META) | 136 | #define REQ_RW_META (1 << __REQ_RW_META) |
136 | #define REQ_COPY_USER (1 << __REQ_COPY_USER) | 137 | #define REQ_COPY_USER (1 << __REQ_COPY_USER) |
138 | #define REQ_INTEGRITY (1 << __REQ_INTEGRITY) | ||
137 | 139 | ||
138 | #define BLK_MAX_CDB 16 | 140 | #define BLK_MAX_CDB 16 |
139 | 141 | ||
@@ -865,6 +867,109 @@ void kblockd_flush_work(struct work_struct *work); | |||
865 | MODULE_ALIAS("block-major-" __stringify(major) "-*") | 867 | MODULE_ALIAS("block-major-" __stringify(major) "-*") |
866 | 868 | ||
867 | 869 | ||
870 | #if defined(CONFIG_BLK_DEV_INTEGRITY) | ||
871 | |||
872 | #define INTEGRITY_FLAG_READ 1 /* verify data integrity on read */ | ||
873 | #define INTEGRITY_FLAG_WRITE 2 /* generate data integrity on write */ | ||
874 | |||
875 | struct blk_integrity_exchg { | ||
876 | void *prot_buf; | ||
877 | void *data_buf; | ||
878 | sector_t sector; | ||
879 | unsigned int data_size; | ||
880 | unsigned short sector_size; | ||
881 | const char *disk_name; | ||
882 | }; | ||
883 | |||
884 | typedef void (integrity_gen_fn) (struct blk_integrity_exchg *); | ||
885 | typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *); | ||
886 | typedef void (integrity_set_tag_fn) (void *, void *, unsigned int); | ||
887 | typedef void (integrity_get_tag_fn) (void *, void *, unsigned int); | ||
888 | |||
889 | struct blk_integrity { | ||
890 | integrity_gen_fn *generate_fn; | ||
891 | integrity_vrfy_fn *verify_fn; | ||
892 | integrity_set_tag_fn *set_tag_fn; | ||
893 | integrity_get_tag_fn *get_tag_fn; | ||
894 | |||
895 | unsigned short flags; | ||
896 | unsigned short tuple_size; | ||
897 | unsigned short sector_size; | ||
898 | unsigned short tag_size; | ||
899 | |||
900 | const char *name; | ||
901 | |||
902 | struct kobject kobj; | ||
903 | }; | ||
904 | |||
905 | extern int blk_integrity_register(struct gendisk *, struct blk_integrity *); | ||
906 | extern void blk_integrity_unregister(struct gendisk *); | ||
907 | extern int blk_integrity_compare(struct block_device *, struct block_device *); | ||
908 | extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); | ||
909 | extern int blk_rq_count_integrity_sg(struct request *); | ||
910 | |||
911 | static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) | ||
912 | { | ||
913 | if (bi) | ||
914 | return bi->tuple_size; | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev) | ||
920 | { | ||
921 | return bdev->bd_disk->integrity; | ||
922 | } | ||
923 | |||
924 | static inline unsigned int bdev_get_tag_size(struct block_device *bdev) | ||
925 | { | ||
926 | struct blk_integrity *bi = bdev_get_integrity(bdev); | ||
927 | |||
928 | if (bi) | ||
929 | return bi->tag_size; | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static inline int bdev_integrity_enabled(struct block_device *bdev, int rw) | ||
935 | { | ||
936 | struct blk_integrity *bi = bdev_get_integrity(bdev); | ||
937 | |||
938 | if (bi == NULL) | ||
939 | return 0; | ||
940 | |||
941 | if (rw == READ && bi->verify_fn != NULL && | ||
942 | test_bit(INTEGRITY_FLAG_READ, &bi->flags)) | ||
943 | return 1; | ||
944 | |||
945 | if (rw == WRITE && bi->generate_fn != NULL && | ||
946 | test_bit(INTEGRITY_FLAG_WRITE, &bi->flags)) | ||
947 | return 1; | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static inline int blk_integrity_rq(struct request *rq) | ||
953 | { | ||
954 | BUG_ON(rq->bio == NULL); | ||
955 | |||
956 | return bio_integrity(rq->bio); | ||
957 | } | ||
958 | |||
959 | #else /* CONFIG_BLK_DEV_INTEGRITY */ | ||
960 | |||
961 | #define blk_integrity_rq(rq) (0) | ||
962 | #define blk_rq_count_integrity_sg(a) (0) | ||
963 | #define blk_rq_map_integrity_sg(a, b) (0) | ||
964 | #define bdev_get_integrity(a) (0) | ||
965 | #define bdev_get_tag_size(a) (0) | ||
966 | #define blk_integrity_compare(a, b) (0) | ||
967 | #define blk_integrity_register(a, b) (0) | ||
968 | #define blk_integrity_unregister(a) do { } while (0); | ||
969 | |||
970 | #endif /* CONFIG_BLK_DEV_INTEGRITY */ | ||
971 | |||
972 | |||
868 | #else /* CONFIG_BLOCK */ | 973 | #else /* CONFIG_BLOCK */ |
869 | /* | 974 | /* |
870 | * stubs for when the block layer is configured out | 975 | * stubs for when the block layer is configured out |