block: Block layer data integrity support
[linux-2.6.git] / include / linux / blkdev.h
index 6a3da67..4a9ed45 100644 (file)
@@ -112,6 +112,7 @@ enum rq_flag_bits {
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_RW_META,          /* metadata io request */
        __REQ_COPY_USER,        /* contains copies of user pages */
+       __REQ_INTEGRITY,        /* integrity metadata has been remapped */
        __REQ_NR_BITS,          /* stops here */
 };
 
@@ -134,6 +135,7 @@ enum rq_flag_bits {
 #define REQ_ALLOCED    (1 << __REQ_ALLOCED)
 #define REQ_RW_META    (1 << __REQ_RW_META)
 #define REQ_COPY_USER  (1 << __REQ_COPY_USER)
+#define REQ_INTEGRITY  (1 << __REQ_INTEGRITY)
 
 #define BLK_MAX_CDB    16
 
@@ -865,6 +867,109 @@ void kblockd_flush_work(struct work_struct *work);
        MODULE_ALIAS("block-major-" __stringify(major) "-*")
 
 
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+
+#define INTEGRITY_FLAG_READ    1       /* verify data integrity on read */
+#define INTEGRITY_FLAG_WRITE   2       /* generate data integrity on write */
+
+struct blk_integrity_exchg {
+       void                    *prot_buf;
+       void                    *data_buf;
+       sector_t                sector;
+       unsigned int            data_size;
+       unsigned short          sector_size;
+       const char              *disk_name;
+};
+
+typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
+typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
+typedef void (integrity_set_tag_fn) (void *, void *, unsigned int);
+typedef void (integrity_get_tag_fn) (void *, void *, unsigned int);
+
+struct blk_integrity {
+       integrity_gen_fn        *generate_fn;
+       integrity_vrfy_fn       *verify_fn;
+       integrity_set_tag_fn    *set_tag_fn;
+       integrity_get_tag_fn    *get_tag_fn;
+
+       unsigned short          flags;
+       unsigned short          tuple_size;
+       unsigned short          sector_size;
+       unsigned short          tag_size;
+
+       const char              *name;
+
+       struct kobject          kobj;
+};
+
+extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
+extern void blk_integrity_unregister(struct gendisk *);
+extern int blk_integrity_compare(struct block_device *, struct block_device *);
+extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
+extern int blk_rq_count_integrity_sg(struct request *);
+
+static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
+{
+       if (bi)
+               return bi->tuple_size;
+
+       return 0;
+}
+
+static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
+{
+       return bdev->bd_disk->integrity;
+}
+
+static inline unsigned int bdev_get_tag_size(struct block_device *bdev)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bdev);
+
+       if (bi)
+               return bi->tag_size;
+
+       return 0;
+}
+
+static inline int bdev_integrity_enabled(struct block_device *bdev, int rw)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bdev);
+
+       if (bi == NULL)
+               return 0;
+
+       if (rw == READ && bi->verify_fn != NULL &&
+           test_bit(INTEGRITY_FLAG_READ, &bi->flags))
+               return 1;
+
+       if (rw == WRITE && bi->generate_fn != NULL &&
+           test_bit(INTEGRITY_FLAG_WRITE, &bi->flags))
+               return 1;
+
+       return 0;
+}
+
+static inline int blk_integrity_rq(struct request *rq)
+{
+       BUG_ON(rq->bio == NULL);
+
+       return bio_integrity(rq->bio);
+}
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+
+#define blk_integrity_rq(rq)                   (0)
+#define blk_rq_count_integrity_sg(a)           (0)
+#define blk_rq_map_integrity_sg(a, b)          (0)
+#define bdev_get_integrity(a)                  (0)
+#define bdev_get_tag_size(a)                   (0)
+#define blk_integrity_compare(a, b)            (0)
+#define blk_integrity_register(a, b)           (0)
+#define blk_integrity_unregister(a)            do { } while (0);
+
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
+
+
 #else /* CONFIG_BLOCK */
 /*
  * stubs for when the block layer is configured out