mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 03:11:11 -04:00
Merge branch 'for-7.1/block-integrity'
Bring in the shared branch with the block layer. * 'for-7.1/block-integrity' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/axboe/linux: block: pass a maxlen argument to bio_iov_iter_bounce block: add fs_bio_integrity helpers block: make max_integrity_io_size public block: prepare generation / verification helpers for fs usage block: add a bdev_has_integrity_csum helper block: factor out a bio_integrity_setup_default helper block: factor out a bio_integrity_action helper Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
@@ -26,7 +26,7 @@ bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
|
||||
obj-$(CONFIG_IOSCHED_BFQ) += bfq.o
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o \
|
||||
bio-integrity-auto.o
|
||||
bio-integrity-auto.o bio-integrity-fs.o
|
||||
obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o
|
||||
obj-$(CONFIG_BLK_WBT) += blk-wbt.o
|
||||
obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o
|
||||
|
||||
@@ -39,7 +39,7 @@ static void bio_integrity_verify_fn(struct work_struct *work)
|
||||
container_of(work, struct bio_integrity_data, work);
|
||||
struct bio *bio = bid->bio;
|
||||
|
||||
blk_integrity_verify_iter(bio, &bid->saved_bio_iter);
|
||||
bio->bi_status = bio_integrity_verify(bio, &bid->saved_bio_iter);
|
||||
bio_integrity_finish(bid);
|
||||
bio_endio(bio);
|
||||
}
|
||||
@@ -50,11 +50,6 @@ static bool bip_should_check(struct bio_integrity_payload *bip)
|
||||
return bip->bip_flags & BIP_CHECK_FLAGS;
|
||||
}
|
||||
|
||||
static bool bi_offload_capable(struct blk_integrity *bi)
|
||||
{
|
||||
return bi->metadata_size == bi->pi_tuple_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* __bio_integrity_endio - Integrity I/O completion function
|
||||
* @bio: Protected bio
|
||||
@@ -84,83 +79,30 @@ bool __bio_integrity_endio(struct bio *bio)
|
||||
/**
|
||||
* bio_integrity_prep - Prepare bio for integrity I/O
|
||||
* @bio: bio to prepare
|
||||
* @action: preparation action needed (BI_ACT_*)
|
||||
*
|
||||
* Checks if the bio already has an integrity payload attached. If it does, the
|
||||
* payload has been generated by another kernel subsystem, and we just pass it
|
||||
* through.
|
||||
* Otherwise allocates integrity payload and for writes the integrity metadata
|
||||
* will be generated. For reads, the completion handler will verify the
|
||||
* metadata.
|
||||
* Allocate the integrity payload. For writes, generate the integrity metadata
|
||||
* and for reads, setup the completion handler to verify the metadata.
|
||||
*
|
||||
* This is used for bios that do not have user integrity payloads attached.
|
||||
*/
|
||||
bool bio_integrity_prep(struct bio *bio)
|
||||
void bio_integrity_prep(struct bio *bio, unsigned int action)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_data *bid;
|
||||
bool set_flags = true;
|
||||
gfp_t gfp = GFP_NOIO;
|
||||
|
||||
if (!bi)
|
||||
return true;
|
||||
|
||||
if (!bio_sectors(bio))
|
||||
return true;
|
||||
|
||||
/* Already protected? */
|
||||
if (bio_integrity(bio))
|
||||
return true;
|
||||
|
||||
switch (bio_op(bio)) {
|
||||
case REQ_OP_READ:
|
||||
if (bi->flags & BLK_INTEGRITY_NOVERIFY) {
|
||||
if (bi_offload_capable(bi))
|
||||
return true;
|
||||
set_flags = false;
|
||||
}
|
||||
break;
|
||||
case REQ_OP_WRITE:
|
||||
/*
|
||||
* Zero the memory allocated to not leak uninitialized kernel
|
||||
* memory to disk for non-integrity metadata where nothing else
|
||||
* initializes the memory.
|
||||
*/
|
||||
if (bi->flags & BLK_INTEGRITY_NOGENERATE) {
|
||||
if (bi_offload_capable(bi))
|
||||
return true;
|
||||
set_flags = false;
|
||||
gfp |= __GFP_ZERO;
|
||||
} else if (bi->metadata_size > bi->pi_tuple_size)
|
||||
gfp |= __GFP_ZERO;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
|
||||
return true;
|
||||
|
||||
bid = mempool_alloc(&bid_pool, GFP_NOIO);
|
||||
bio_integrity_init(bio, &bid->bip, &bid->bvec, 1);
|
||||
bid->bio = bio;
|
||||
bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY;
|
||||
bio_integrity_alloc_buf(bio, gfp & __GFP_ZERO);
|
||||
|
||||
bip_set_seed(&bid->bip, bio->bi_iter.bi_sector);
|
||||
|
||||
if (set_flags) {
|
||||
if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
|
||||
bid->bip.bip_flags |= BIP_IP_CHECKSUM;
|
||||
if (bi->csum_type)
|
||||
bid->bip.bip_flags |= BIP_CHECK_GUARD;
|
||||
if (bi->flags & BLK_INTEGRITY_REF_TAG)
|
||||
bid->bip.bip_flags |= BIP_CHECK_REFTAG;
|
||||
}
|
||||
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
|
||||
if (action & BI_ACT_CHECK)
|
||||
bio_integrity_setup_default(bio);
|
||||
|
||||
/* Auto-generate integrity metadata if this is a write */
|
||||
if (bio_data_dir(bio) == WRITE && bip_should_check(&bid->bip))
|
||||
blk_integrity_generate(bio);
|
||||
bio_integrity_generate(bio);
|
||||
else
|
||||
bid->saved_bio_iter = bio->bi_iter;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(bio_integrity_prep);
|
||||
|
||||
|
||||
81
block/bio-integrity-fs.c
Normal file
81
block/bio-integrity-fs.c
Normal file
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2025 Christoph Hellwig.
|
||||
*/
|
||||
#include <linux/blk-integrity.h>
|
||||
#include <linux/bio-integrity.h>
|
||||
#include "blk.h"
|
||||
|
||||
struct fs_bio_integrity_buf {
|
||||
struct bio_integrity_payload bip;
|
||||
struct bio_vec bvec;
|
||||
};
|
||||
|
||||
static struct kmem_cache *fs_bio_integrity_cache;
|
||||
static mempool_t fs_bio_integrity_pool;
|
||||
|
||||
unsigned int fs_bio_integrity_alloc(struct bio *bio)
|
||||
{
|
||||
struct fs_bio_integrity_buf *iib;
|
||||
unsigned int action;
|
||||
|
||||
action = bio_integrity_action(bio);
|
||||
if (!action)
|
||||
return 0;
|
||||
|
||||
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOIO);
|
||||
bio_integrity_init(bio, &iib->bip, &iib->bvec, 1);
|
||||
|
||||
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
|
||||
if (action & BI_ACT_CHECK)
|
||||
bio_integrity_setup_default(bio);
|
||||
return action;
|
||||
}
|
||||
|
||||
void fs_bio_integrity_free(struct bio *bio)
|
||||
{
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
|
||||
bio_integrity_free_buf(bip);
|
||||
mempool_free(container_of(bip, struct fs_bio_integrity_buf, bip),
|
||||
&fs_bio_integrity_pool);
|
||||
|
||||
bio->bi_integrity = NULL;
|
||||
bio->bi_opf &= ~REQ_INTEGRITY;
|
||||
}
|
||||
|
||||
void fs_bio_integrity_generate(struct bio *bio)
|
||||
{
|
||||
if (fs_bio_integrity_alloc(bio))
|
||||
bio_integrity_generate(bio);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fs_bio_integrity_generate);
|
||||
|
||||
int fs_bio_integrity_verify(struct bio *bio, sector_t sector, unsigned int size)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
|
||||
/*
|
||||
* Reinitialize bip->bip_iter.
|
||||
*
|
||||
* This is for use in the submitter after the driver is done with the
|
||||
* bio. Requires the submitter to remember the sector and the size.
|
||||
*/
|
||||
memset(&bip->bip_iter, 0, sizeof(bip->bip_iter));
|
||||
bip->bip_iter.bi_sector = sector;
|
||||
bip->bip_iter.bi_size = bio_integrity_bytes(bi, size >> SECTOR_SHIFT);
|
||||
return blk_status_to_errno(bio_integrity_verify(bio, &bip->bip_iter));
|
||||
}
|
||||
|
||||
static int __init fs_bio_integrity_init(void)
|
||||
{
|
||||
fs_bio_integrity_cache = kmem_cache_create("fs_bio_integrity",
|
||||
sizeof(struct fs_bio_integrity_buf), 0,
|
||||
SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
|
||||
if (mempool_init_slab_pool(&fs_bio_integrity_pool, BIO_POOL_SIZE,
|
||||
fs_bio_integrity_cache))
|
||||
panic("fs_bio_integrity: can't create pool\n");
|
||||
return 0;
|
||||
}
|
||||
fs_initcall(fs_bio_integrity_init);
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/blk-integrity.h>
|
||||
#include <linux/t10-pi.h>
|
||||
#include "blk.h"
|
||||
|
||||
struct bio_integrity_alloc {
|
||||
@@ -16,6 +17,53 @@ struct bio_integrity_alloc {
|
||||
|
||||
static mempool_t integrity_buf_pool;
|
||||
|
||||
static bool bi_offload_capable(struct blk_integrity *bi)
|
||||
{
|
||||
return bi->metadata_size == bi->pi_tuple_size;
|
||||
}
|
||||
|
||||
unsigned int __bio_integrity_action(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
|
||||
if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
|
||||
return 0;
|
||||
|
||||
switch (bio_op(bio)) {
|
||||
case REQ_OP_READ:
|
||||
if (bi->flags & BLK_INTEGRITY_NOVERIFY) {
|
||||
if (bi_offload_capable(bi))
|
||||
return 0;
|
||||
return BI_ACT_BUFFER;
|
||||
}
|
||||
return BI_ACT_BUFFER | BI_ACT_CHECK;
|
||||
case REQ_OP_WRITE:
|
||||
/*
|
||||
* Flush masquerading as write?
|
||||
*/
|
||||
if (!bio_sectors(bio))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Zero the memory allocated to not leak uninitialized kernel
|
||||
* memory to disk for non-integrity metadata where nothing else
|
||||
* initializes the memory.
|
||||
*/
|
||||
if (bi->flags & BLK_INTEGRITY_NOGENERATE) {
|
||||
if (bi_offload_capable(bi))
|
||||
return 0;
|
||||
return BI_ACT_BUFFER | BI_ACT_ZERO;
|
||||
}
|
||||
|
||||
if (bi->metadata_size > bi->pi_tuple_size)
|
||||
return BI_ACT_BUFFER | BI_ACT_CHECK | BI_ACT_ZERO;
|
||||
return BI_ACT_BUFFER | BI_ACT_CHECK;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__bio_integrity_action);
|
||||
|
||||
void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
@@ -53,6 +101,22 @@ void bio_integrity_free_buf(struct bio_integrity_payload *bip)
|
||||
kfree(bvec_virt(bv));
|
||||
}
|
||||
|
||||
void bio_integrity_setup_default(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
|
||||
bip_set_seed(bip, bio->bi_iter.bi_sector);
|
||||
|
||||
if (bi->csum_type) {
|
||||
bip->bip_flags |= BIP_CHECK_GUARD;
|
||||
if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
|
||||
bip->bip_flags |= BIP_IP_CHECKSUM;
|
||||
}
|
||||
if (bi->flags & BLK_INTEGRITY_REF_TAG)
|
||||
bip->bip_flags |= BIP_CHECK_REFTAG;
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_integrity_free - Free bio integrity payload
|
||||
* @bio: bio containing bip to be freed
|
||||
|
||||
17
block/bio.c
17
block/bio.c
@@ -1327,9 +1327,10 @@ static void bio_free_folios(struct bio *bio)
|
||||
}
|
||||
}
|
||||
|
||||
static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter)
|
||||
static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
|
||||
size_t maxlen)
|
||||
{
|
||||
size_t total_len = iov_iter_count(iter);
|
||||
size_t total_len = min(maxlen, iov_iter_count(iter));
|
||||
|
||||
if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
|
||||
return -EINVAL;
|
||||
@@ -1367,9 +1368,10 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter)
|
||||
static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
|
||||
size_t maxlen)
|
||||
{
|
||||
size_t len = min(iov_iter_count(iter), SZ_1M);
|
||||
size_t len = min3(iov_iter_count(iter), maxlen, SZ_1M);
|
||||
struct folio *folio;
|
||||
|
||||
folio = folio_alloc_greedy(GFP_KERNEL, &len);
|
||||
@@ -1408,6 +1410,7 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter)
|
||||
* bio_iov_iter_bounce - bounce buffer data from an iter into a bio
|
||||
* @bio: bio to send
|
||||
* @iter: iter to read from / write into
|
||||
* @maxlen: maximum size to bounce
|
||||
*
|
||||
* Helper for direct I/O implementations that need to bounce buffer because
|
||||
* we need to checksum the data or perform other operations that require
|
||||
@@ -1415,11 +1418,11 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter)
|
||||
* copies the data into it. Needs to be paired with bio_iov_iter_unbounce()
|
||||
* called on completion.
|
||||
*/
|
||||
int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter)
|
||||
int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen)
|
||||
{
|
||||
if (op_is_write(bio_op(bio)))
|
||||
return bio_iov_iter_bounce_write(bio, iter);
|
||||
return bio_iov_iter_bounce_read(bio, iter);
|
||||
return bio_iov_iter_bounce_write(bio, iter, maxlen);
|
||||
return bio_iov_iter_bounce_read(bio, iter, maxlen);
|
||||
}
|
||||
|
||||
static void bvec_unpin(struct bio_vec *bv, bool mark_dirty)
|
||||
|
||||
@@ -3143,6 +3143,7 @@ void blk_mq_submit_bio(struct bio *bio)
|
||||
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
|
||||
struct blk_plug *plug = current->plug;
|
||||
const int is_sync = op_is_sync(bio->bi_opf);
|
||||
unsigned int integrity_action;
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
unsigned int nr_segs;
|
||||
struct request *rq;
|
||||
@@ -3195,8 +3196,9 @@ void blk_mq_submit_bio(struct bio *bio)
|
||||
if (!bio)
|
||||
goto queue_exit;
|
||||
|
||||
if (!bio_integrity_prep(bio))
|
||||
goto queue_exit;
|
||||
integrity_action = bio_integrity_action(bio);
|
||||
if (integrity_action)
|
||||
bio_integrity_prep(bio, integrity_action);
|
||||
|
||||
blk_mq_bio_issue_init(q, bio);
|
||||
if (blk_mq_attempt_bio_merge(q, bio, nr_segs))
|
||||
|
||||
@@ -123,19 +123,6 @@ static int blk_validate_zoned_limits(struct queue_limits *lim)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum size of I/O that needs a block layer integrity buffer. Limited
|
||||
* by the number of intervals for which we can fit the integrity buffer into
|
||||
* the buffer size. Because the buffer is a single segment it is also limited
|
||||
* by the maximum segment size.
|
||||
*/
|
||||
static inline unsigned int max_integrity_io_size(struct queue_limits *lim)
|
||||
{
|
||||
return min_t(unsigned int, lim->max_segment_size,
|
||||
(BLK_INTEGRITY_MAX_SIZE / lim->integrity.metadata_size) <<
|
||||
lim->integrity.interval_exp);
|
||||
}
|
||||
|
||||
static int blk_validate_integrity_limits(struct queue_limits *lim)
|
||||
{
|
||||
struct blk_integrity *bi = &lim->integrity;
|
||||
|
||||
@@ -699,8 +699,10 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
|
||||
const struct blk_holder_ops *hops, struct file *bdev_file);
|
||||
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
|
||||
|
||||
void blk_integrity_generate(struct bio *bio);
|
||||
void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter);
|
||||
void bio_integrity_generate(struct bio *bio);
|
||||
blk_status_t bio_integrity_verify(struct bio *bio,
|
||||
struct bvec_iter *saved_iter);
|
||||
|
||||
void blk_integrity_prepare(struct request *rq);
|
||||
void blk_integrity_complete(struct request *rq, unsigned int nr_bytes);
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
void blk_integrity_generate(struct bio *bio)
|
||||
void bio_integrity_generate(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
@@ -404,7 +404,7 @@ void blk_integrity_generate(struct bio *bio)
|
||||
}
|
||||
}
|
||||
|
||||
void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter)
|
||||
blk_status_t bio_integrity_verify(struct bio *bio, struct bvec_iter *saved_iter)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
@@ -439,11 +439,11 @@ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter)
|
||||
}
|
||||
kunmap_local(kaddr);
|
||||
|
||||
if (ret) {
|
||||
bio->bi_status = ret;
|
||||
return;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
||||
void blk_integrity_prepare(struct request *rq)
|
||||
|
||||
@@ -1435,14 +1435,16 @@ static void btt_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
struct btt *btt = bio->bi_bdev->bd_disk->private_data;
|
||||
unsigned int integrity_action;
|
||||
struct bvec_iter iter;
|
||||
unsigned long start;
|
||||
struct bio_vec bvec;
|
||||
int err = 0;
|
||||
bool do_acct;
|
||||
|
||||
if (!bio_integrity_prep(bio))
|
||||
return;
|
||||
integrity_action = bio_integrity_action(bio);
|
||||
if (integrity_action)
|
||||
bio_integrity_prep(bio, integrity_action);
|
||||
|
||||
do_acct = blk_queue_io_stat(bio->bi_bdev->bd_disk->queue);
|
||||
if (do_acct)
|
||||
|
||||
@@ -351,7 +351,7 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
|
||||
bio->bi_end_io = iomap_dio_bio_end_io;
|
||||
|
||||
if (dio->flags & IOMAP_DIO_BOUNCE)
|
||||
ret = bio_iov_iter_bounce(bio, dio->submit.iter);
|
||||
ret = bio_iov_iter_bounce(bio, dio->submit.iter, BIO_MAX_SIZE);
|
||||
else
|
||||
ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
|
||||
alignment - 1);
|
||||
|
||||
@@ -78,7 +78,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, unsigned int len,
|
||||
int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter);
|
||||
int bio_integrity_map_iter(struct bio *bio, struct uio_meta *meta);
|
||||
void bio_integrity_unmap_user(struct bio *bio);
|
||||
bool bio_integrity_prep(struct bio *bio);
|
||||
void bio_integrity_prep(struct bio *bio, unsigned int action);
|
||||
void bio_integrity_advance(struct bio *bio, unsigned int bytes_done);
|
||||
void bio_integrity_trim(struct bio *bio);
|
||||
int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask);
|
||||
@@ -104,9 +104,8 @@ static inline void bio_integrity_unmap_user(struct bio *bio)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool bio_integrity_prep(struct bio *bio)
|
||||
static inline void bio_integrity_prep(struct bio *bio, unsigned int action)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
|
||||
@@ -144,5 +143,12 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page,
|
||||
|
||||
void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer);
|
||||
void bio_integrity_free_buf(struct bio_integrity_payload *bip);
|
||||
void bio_integrity_setup_default(struct bio *bio);
|
||||
|
||||
unsigned int fs_bio_integrity_alloc(struct bio *bio);
|
||||
void fs_bio_integrity_free(struct bio *bio);
|
||||
void fs_bio_integrity_generate(struct bio *bio);
|
||||
int fs_bio_integrity_verify(struct bio *bio, sector_t sector,
|
||||
unsigned int size);
|
||||
|
||||
#endif /* _LINUX_BIO_INTEGRITY_H */
|
||||
|
||||
@@ -474,7 +474,7 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty);
|
||||
extern void bio_set_pages_dirty(struct bio *bio);
|
||||
extern void bio_check_pages_dirty(struct bio *bio);
|
||||
|
||||
int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter);
|
||||
int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen);
|
||||
void bio_iov_iter_unbounce(struct bio *bio, bool is_error, bool mark_dirty);
|
||||
|
||||
extern void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter,
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
|
||||
struct request;
|
||||
|
||||
/*
|
||||
* Maximum contiguous integrity buffer allocation.
|
||||
*/
|
||||
#define BLK_INTEGRITY_MAX_SIZE SZ_2M
|
||||
|
||||
enum blk_integrity_flags {
|
||||
BLK_INTEGRITY_NOVERIFY = 1 << 0,
|
||||
BLK_INTEGRITY_NOGENERATE = 1 << 1,
|
||||
@@ -180,4 +175,27 @@ static inline struct bio_vec rq_integrity_vec(struct request *rq)
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
enum bio_integrity_action {
|
||||
BI_ACT_BUFFER = (1u << 0), /* allocate buffer */
|
||||
BI_ACT_CHECK = (1u << 1), /* generate / verify PI */
|
||||
BI_ACT_ZERO = (1u << 2), /* zero buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* bio_integrity_action - return the integrity action needed for a bio
|
||||
* @bio: bio to operate on
|
||||
*
|
||||
* Returns the mask of integrity actions (BI_ACT_*) that need to be performed
|
||||
* for @bio.
|
||||
*/
|
||||
unsigned int __bio_integrity_action(struct bio *bio);
|
||||
static inline unsigned int bio_integrity_action(struct bio *bio)
|
||||
{
|
||||
if (!blk_get_integrity(bio->bi_bdev->bd_disk))
|
||||
return 0;
|
||||
if (bio_integrity(bio))
|
||||
return 0;
|
||||
return __bio_integrity_action(bio);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BLK_INTEGRITY_H */
|
||||
|
||||
@@ -1477,14 +1477,18 @@ static inline bool bdev_synchronous(struct block_device *bdev)
|
||||
return bdev->bd_disk->queue->limits.features & BLK_FEAT_SYNCHRONOUS;
|
||||
}
|
||||
|
||||
static inline bool bdev_has_integrity_csum(struct block_device *bdev)
|
||||
{
|
||||
struct queue_limits *lim = bdev_limits(bdev);
|
||||
|
||||
return IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
|
||||
lim->integrity.csum_type != BLK_INTEGRITY_CSUM_NONE;
|
||||
}
|
||||
|
||||
static inline bool bdev_stable_writes(struct block_device *bdev)
|
||||
{
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
|
||||
q->limits.integrity.csum_type != BLK_INTEGRITY_CSUM_NONE)
|
||||
return true;
|
||||
return q->limits.features & BLK_FEAT_STABLE_WRITES;
|
||||
return bdev_has_integrity_csum(bdev) ||
|
||||
(bdev_limits(bdev)->features & BLK_FEAT_STABLE_WRITES);
|
||||
}
|
||||
|
||||
static inline bool blk_queue_write_cache(struct request_queue *q)
|
||||
@@ -1877,6 +1881,24 @@ static inline int bio_split_rw_at(struct bio *bio,
|
||||
return bio_split_io_at(bio, lim, segs, max_bytes, lim->dma_alignment);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum contiguous integrity buffer allocation.
|
||||
*/
|
||||
#define BLK_INTEGRITY_MAX_SIZE SZ_2M
|
||||
|
||||
/*
|
||||
* Maximum size of I/O that needs a block layer integrity buffer. Limited
|
||||
* by the number of intervals for which we can fit the integrity buffer into
|
||||
* the buffer size. Because the buffer is a single segment it is also limited
|
||||
* by the maximum segment size.
|
||||
*/
|
||||
static inline unsigned int max_integrity_io_size(struct queue_limits *lim)
|
||||
{
|
||||
return min_t(unsigned int, lim->max_segment_size,
|
||||
(BLK_INTEGRITY_MAX_SIZE / lim->integrity.metadata_size) <<
|
||||
lim->integrity.interval_exp);
|
||||
}
|
||||
|
||||
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
|
||||
|
||||
#endif /* _LINUX_BLKDEV_H */
|
||||
|
||||
Reference in New Issue
Block a user