Currently all integrity prep hooks are open-coded, and if prepare fails we ignore it's code and fail bio with EIO. Let's return real error to upper layer, so later caller may react accordingly. For example retry in case of ENOMEM. Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx> --- block/blk-core.c | 5 +---- block/blk-mq.c | 8 ++------ drivers/nvdimm/blk.c | 13 ++----------- drivers/nvdimm/btt.c | 13 ++----------- include/linux/bio.h | 25 +++++++++++++++++++++++++ 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index d772c22..071a998 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1637,11 +1637,8 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) blk_queue_split(q, &bio, q->bio_split); - if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { - bio->bi_error = -EIO; - bio_endio(bio); + if (bio_integrity_setup(bio)) return BLK_QC_T_NONE; - } if (op_is_flush(bio->bi_opf)) { spin_lock_irq(q->queue_lock); diff --git a/block/blk-mq.c b/block/blk-mq.c index 08a49c6..a9931ec 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1489,10 +1489,8 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) blk_queue_bounce(q, &bio); - if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { - bio_io_error(bio); + if (bio_integrity_setup(bio)) return BLK_QC_T_NONE; - } blk_queue_split(q, &bio, q->bio_split); @@ -1611,10 +1609,8 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) blk_queue_bounce(q, &bio); - if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { - bio_io_error(bio); + if (bio_integrity_setup(bio)) return BLK_QC_T_NONE; - } blk_queue_split(q, &bio, q->bio_split); diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 9faaa96..1edb3f3 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -179,16 +179,8 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) int err = 0, rw; bool do_acct; - /* - * bio_integrity_enabled also checks if the bio already has an - * integrity payload attached. If it does, we *don't* do a - * bio_integrity_prep here - the payload has been generated by - * another kernel subsystem, and we just pass it through. - */ - if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { - bio->bi_error = -EIO; - goto out; - } + if (bio_integrity_setup(bio)) + return BLK_QC_T_NONE; bip = bio_integrity(bio); nsblk = q->queuedata; @@ -212,7 +204,6 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) if (do_acct) nd_iostat_end(bio, start); - out: bio_endio(bio); return BLK_QC_T_NONE; } diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index 368795a..03ded8d 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1158,16 +1158,8 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) int err = 0; bool do_acct; - /* - * bio_integrity_enabled also checks if the bio already has an - * integrity payload attached. If it does, we *don't* do a - * bio_integrity_prep here - the payload has been generated by - * another kernel subsystem, and we just pass it through. - */ - if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { - bio->bi_error = -EIO; - goto out; - } + if (bio_integrity_setup(bio)) + return BLK_QC_T_NONE; do_acct = nd_iostat_start(bio, &start); bio_for_each_segment(bvec, bio, iter) { @@ -1194,7 +1186,6 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) if (do_acct) nd_iostat_end(bio, start); -out: bio_endio(bio); return BLK_QC_T_NONE; } diff --git a/include/linux/bio.h b/include/linux/bio.h index 350f71d..f477327 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -738,6 +738,26 @@ extern int bioset_integrity_create(struct bio_set *, int); extern void bioset_integrity_free(struct bio_set *); extern void bio_integrity_init(void); +static inline int bio_integrity_setup(struct bio *bio) +{ + int err = 0; + + /* + * bio_integrity_enabled also checks if the bio already has an + * integrity payload attached. If it does, we *don't* do a + * bio_integrity_prep here - the payload has been generated by + * another kernel subsystem, and we just pass it through. + */ + if (bio_integrity_enabled(bio)) { + err = bio_integrity_prep(bio); + if (err) { + bio->bi_error = err; + bio_endio(bio); + } + } + return err; +} + #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline void *bio_integrity(struct bio *bio) @@ -765,6 +785,11 @@ static inline int bio_integrity_prep(struct bio *bio) return 0; } +static int bio_integrity_setup(struct bio *bio) +{ + return 0; +} + static inline void bio_integrity_free(struct bio *bio) { return; -- 2.9.3