Block Layer Data Integrity
Subsystems (4)
PATCH 1/1 Block Layer Data Integrity
These patches allow data integrity information (checksum and more) to be attached to I/Os at the block/filesystem layers and transferred through the entire I/O stack all the way to the physical storage device.
The integrity metadata can be generated in close proximity to the original data. Capable host adapters, RAID arrays and physical disks can verify the data integrity and abort I/Os in case of a mismatch.
Changes:
- Add "if in doubt" to Kconfig
- Make blk_rq_count_integrity_sg() more readable
- Queue integrity sysfs fixes
- Fix two struct bi leaks
- Rename struct bip to bio_integrity_payload
- Introduce bio_integrity_hw_sectors() that converts from block layer (512b) sectors to hardware sectors
- Fix kunmap_atomic() abuse
- Replace ?: constructs with if()
- Add __GFP_NOFAIL to bio_integrity_prep() allocation
PATCH 1/1 block: Globalize bio_set and bio_vec_slab
Move struct bio_set and biovec_slab definitions to bio.h so they can be used outside of bio.c.
---
2 files changed, 31 insertions(+), 28 deletions(-) fs/bio.c | 30 ++---------------------------- include/linux/bio.h | 29 +++++++++++++++++++++++++++++
fs/bio.c +2 -28
@@ -28,24 +28,9 @@#include <linux/blktrace_api.h> #include <scsi/sg.h> /* for struct sg_iovec */ -#define BIO_POOL_SIZE 2 -static struct kmem_cache *bio_slab__read_mostly ; -#define BIOVEC_NR_POOLS 6 - -/* -* a small number of entries is fine, not going to be performance critical. -* basically we just need to survive -*/ -#define BIO_SPLIT_ENTRIES 2mempool_t *bio_split_pool__read_mostly ; - -struct biovec_slab { -int nr_vecs; -char *name; -struct kmem_cache *slab; -};/* * if you change this list, also change bvec_alloc or things will
@@ -60,23 +45,12 @@ static struct biovec_slab bvec_slabs[BIO#undef BV/* -* bio_set is used to allow other portions of the IO system to -* allocate their own private memory pools for bio and iovec structures. -* These memory pools in turn all allocate from the bio_slab -* and the bvec_slabs[]. -*/ -struct bio_set { -mempool_t *bio_pool; -mempool_t *bvec_pools[BIOVEC_NR_POOLS ]; -}; - -/* * fs_bio_set is the bio_set containing bio and iovec memory pools used by * IO code that does not need private memory pools. */ -static struct bio_set *fs_bio_set; +struct bio_set *fs_bio_set; -static inline struct bio_vec *bvec_alloc_bs (gfp_t gfp_mask,int nr,unsigned long *idx,struct bio_set *bs) +struct bio_vec *bvec_alloc_bs (gfp_t gfp_mask,int nr,unsigned long *idx,struct bio_set *bs) {struct bio_vec *bvl;
include/linux/bio.h +29 -0
@@ -333,6 +333,35 @@ extern struct bio *bio_copy_user_iov(str int, int);extern int bio_uncopy_user (struct bio *);void zero_fill_bio (struct bio *bio); +extern struct bio_vec *bvec_alloc_bs (gfp_t ,int ,unsigned long *,struct bio_set *); + +/* +* bio_set is used to allow other portions of the IO system to +* allocate their own private memory pools for bio and iovec structures. +* These memory pools in turn all allocate from the bio_slab +* and the bvec_slabs[]. +*/ +#define BIO_POOL_SIZE 2 +#define BIOVEC_NR_POOLS 6 + +struct bio_set { +mempool_t *bio_pool; +mempool_t *bvec_pools[BIOVEC_NR_POOLS ]; +}; + +struct biovec_slab { +int nr_vecs; +char *name; +struct kmem_cache *slab; +}; + +extern struct bio_set *fs_bio_set; + +/* +* a small number of entries is fine, not going to be performance critical. +* basically we just need to survive +*/ +#define BIO_SPLIT_ENTRIES 2#ifdef CONFIG_HIGHMEM /*
PATCH 1/1 block: Block layer data integrity support
In reply to Martin K. PetersenSome 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.
---
13 files changed, 1355 insertions(+), 7 deletions(-) block/Kconfig | 12 block/Makefile | 1 block/blk-core.c | 7 block/blk-integrity.c | 382 +++++++++++++++++++++++++ block/blk-merge.c | 3 block/blk.h | 8 block/elevator.c | 6 fs/Makefile | 1 fs/bio-integrity.c | 708 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/bio.c | 32 +- include/linux/bio.h | 94 ++++++ include/linux/blkdev.h | 105 +++++++ include/linux/genhd.h | 3
block/Kconfig +12 -0
@@ -81,6 +81,18 @@ config BLK_DEV_BSG If unsure, say N. +config BLK_DEV_INTEGRITY + bool "Block layer data integrity support" + ---help--- + Some storage devices allow extra information to be + stored/retrieved to help protect the data. The block layer + data integrity option provides hooks which can be used by + filesystems to ensure better data integrity. + + Say yes here if you have a storage device that provides the + T10/SCSI Data Integrity Field or the T13/ATA External Path + Protection. If in doubt, say N. + endif # BLOCK config BLOCK_COMPAT
block/Makefile +1 -0
@@ -14,3 +14,4 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o +obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
block/blk-core.c +7 -0
@@ -143,6 +143,10 @@ static void req_bio_endio(struct request bio->bi_size -= nbytes; bio->bi_sector += (nbytes >>9 ); + +if (bio_integrity (bio)) +bio_integrity_advance (bio, nbytes); +if (bio->bi_size ==0 )bio_endio (bio, error); }else {
@@ -1381,6 +1385,9 @@ end_io:*/ blk_partition_remap (bio); +if (bio_integrity_enabled (bio) &&bio_integrity_prep (bio)) + goto end_io; +if (old_sector !=-1 )blk_add_trace_remap (q, bio, old_dev, bio->bi_sector, old_sector);
block/blk-integrity.c new file +382 -0
382 lines not on this page · raw message
block/blk-merge.c +3 -0
@@ -441,6 +441,9 @@ static int attempt_merge(struct request_ || next->special)return 0 ; +if (blk_integrity_rq (req) !=blk_integrity_rq (next)) +return 0 ; +/* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn
block/blk.h +8 -0
@@ -51,4 +51,12 @@ static inline int queue_congestion_off_t return q->nr_congestion_off; } +#if defined(CONFIG_BLK_DEV_INTEGRITY ) + +#define rq_for_each_integrity_segment (bvl, _rq, _iter) \ + __rq_for_each_bio(_iter.bio, _rq) \ + bip_for_each_vec(bvl, _iter.bio->bi_integrity, _iter.i) + +#endif /* BLK_DEV_INTEGRITY */ +#endif
block/elevator.c +6 -0
@@ -84,6 +84,12 @@ int elv_rq_merge_ok(struct request *rq,* must be same device and not a special request */ if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) +return 0 ; + +/* +* only merge integrity protected bio into ditto rq +*/ +if (bio_integrity (bio) !=blk_integrity_rq (rq))return 0 ;if (!elv_iosched_allow_merge (rq, bio))
fs/Makefile +1 -0
@@ -19,6 +19,7 @@ obj-y += no-block.o obj-y += no-block.o endif +obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_INOTIFY_USER) += inotify_user.o obj-$(CONFIG_EPOLL) += eventpoll.o
fs/bio-integrity.c new file +708 -0
708 lines not on this page · raw message
fs/bio.c +29 -3
@@ -50,6 +50,11 @@ static struct biovec_slab bvec_slabs[BIO*/ struct bio_set *fs_bio_set; +inline unsigned int bvec_nr_vecs (unsigned short idx) +{ +return bvec_slabs[idx].nr_vecs; +} +struct bio_vec *bvec_alloc_bs (gfp_t gfp_mask,int nr,unsigned long *idx,struct bio_set *bs) {struct bio_vec *bvl;
@@ -90,6 +95,9 @@ void bio_free(struct bio *bio, struct bimempool_free (bio->bi_io_vec, bio_set->bvec_pools[pool_idx]); } + +if (bio_integrity (bio)) +bio_integrity_free (bio, bio_set);mempool_free (bio, bio_set->bio_pool); }
@@ -249,9 +257,19 @@ struct bio *bio_clone(struct bio *bio, g {struct bio *b =bio_alloc_bioset (gfp_mask, bio->bi_max_vecs, fs_bio_set); -if (b) { - b->bi_destructor = bio_fs_destructor; -__bio_clone (b, bio); +if (!b) +return NULL ; + + b->bi_destructor = bio_fs_destructor; +__bio_clone (b, bio); + +if (bio_integrity (bio)) { +int ret; + + ret =bio_integrity_clone (b, bio, fs_bio_set); + +if (ret <0 ) +return NULL ; }return b;
@@ -1223,6 +1241,9 @@ struct bio_pair *bio_split(struct bio *b bp->bio1.bi_private = bi; bp->bio2.bi_private = pool; +if (bio_integrity (bi)) +bio_integrity_split (bi, bp, first_sectors); +return bp; }
@@ -1264,6 +1285,7 @@ void bioset_free(struct bio_set *bs)if (bs->bio_pool)mempool_destroy (bs->bio_pool); +bioset_integrity_free (bs);biovec_free_pools (bs);kfree (bs);
@@ -1278,6 +1300,9 @@ struct bio_set *bioset_create(int bio_po bs->bio_pool =mempool_create_slab_pool (bio_pool_size, bio_slab);if (!bs->bio_pool) + goto bad; + +if (bioset_integrity_create (bs, bio_pool_size)) goto bad;if (!biovec_create_pools (bs, bvec_pool_size))
@@ -1306,6 +1331,7 @@ static int __init init_bio(void) { bio_slab =KMEM_CACHE (bio,SLAB_HWCACHE_ALIGN |SLAB_PANIC ); +bio_integrity_init_slab ();biovec_init_slabs (); fs_bio_set =bioset_create (BIO_POOL_SIZE ,2 );
include/linux/bio.h +90 -4
135 lines not on this page · raw message
include/linux/blkdev.h +105 -0
123 lines not on this page · raw message
include/linux/genhd.h +3 -0
@@ -141,6 +141,9 @@ struct gendisk {struct disk_stats dkstats;#endif struct work_struct async_notify; +#ifdef CONFIG_BLK_DEV_INTEGRITY +struct blk_integrity *integrity; +#endif };/*
PATCH 1/1 block: Data integrity infrastructure documentation
In reply to Martin K. Petersen---
2 files changed, 361 insertions(+)
Documentation/ABI/testing/sysfs-block | 34 +++Documentation/block/data-integrity.txt | 327 ++++++++++++++++++++++++++++++++
Documentation/ABI/testing/sysfs-block +34 -0
@@ -26,3 +26,37 @@ Description: I/O statistics of partition <part>. The format is the same as the above-written /sys/block/<disk>/stat format. + + +What: /sys/block/<disk>/integrity/format +Date: June 2008 +Contact: Martin K. Petersen <[email protected]> +Description: + Metadata format for integrity capable block device. + E.g. T10-DIF-TYPE1-CRC. + + +What: /sys/block/<disk>/integrity/read_verify +Date: June 2008 +Contact: Martin K. Petersen <[email protected]> +Description: + Indicates whether the block layer should verify the + integrity of read requests serviced by devices that + support sending integrity metadata. + + +What: /sys/block/<disk>/integrity/tag_size +Date: June 2008 +Contact: Martin K. Petersen <[email protected]> +Description: + Number of bytes of integrity tag space available per + 512 bytes of data. + + +What: /sys/block/<disk>/integrity/write_generate +Date: June 2008 +Contact: Martin K. Petersen <[email protected]> +Description: + Indicates whether the block layer should automatically + generate checksums for write requests bound for + devices that support receiving integrity metadata.
Documentation/block/data-integrity.txt new file +327 -0
327 lines not on this page · raw message
Quoted 22 lines · Martin K. Petersen
These patches allow data integrity information (checksum and more) to be attached to I/Os at the block/filesystem layers and transferred through the entire I/O stack all the way to the physical storage device.
The integrity metadata can be generated in close proximity to the original data. Capable host adapters, RAID arrays and physical disks can verify the data integrity and abort I/Os in case of a mismatch.
Changes:
- Add "if in doubt" to
Kconfig- Make
blk_rq_count_integrity_sg()more readable- Queue integrity sysfs fixes
- Fix two struct bi leaks
- Rename struct bip to
bio_integrity_payload
Quoted 8 lines
- Introduce
bio_integrity_hw_sectors()that converts from block layer (512b) sectors to hardware sectors- Fix
kunmap_atomic()abuse- Replace ?: constructs with
if()- Add
__GFP_NOFAILtobio_integrity_prep()allocation
Thanks Martin, looks good to me now. Applied to pending 2.6.27 queue.
Signature · 1 line
Jens Axboe