summaryrefslogtreecommitdiff
path: root/block/blk-core.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2020-09-16 06:53:14 +0300
committerJens Axboe <axboe@kernel.dk>2020-10-05 19:47:43 +0300
commit93f221ae08381e994ac9f9ff6aa743e612e49718 (patch)
treefe3f7bb6254559fb0d7a84fc467389a5af30c821 /block/blk-core.c
parent07560151db960d26b425410d6fd778e6757a5da2 (diff)
downloadlinux-93f221ae08381e994ac9f9ff6aa743e612e49718.tar.xz
block: make blk_crypto_rq_bio_prep() able to fail
blk_crypto_rq_bio_prep() assumes its gfp_mask argument always includes __GFP_DIRECT_RECLAIM, so that the mempool_alloc() will always succeed. However, blk_crypto_rq_bio_prep() might be called with GFP_ATOMIC via setup_clone() in drivers/md/dm-rq.c. This case isn't currently reachable with a bio that actually has an encryption context. However, it's fragile to rely on this. Just make blk_crypto_rq_bio_prep() able to fail. Suggested-by: Satya Tangirala <satyat@google.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Mike Snitzer <snitzer@redhat.com> Reviewed-by: Satya Tangirala <satyat@google.com> Cc: Miaohe Lin <linmiaohe@huawei.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-core.c')
-rw-r--r--block/blk-core.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 4884f1e7451b..3b01e7f3c7a3 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1617,8 +1617,10 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
if (rq->bio) {
rq->biotail->bi_next = bio;
rq->biotail = bio;
- } else
+ } else {
rq->bio = rq->biotail = bio;
+ }
+ bio = NULL;
}
/* Copy attributes of the original request to the clone request. */
@@ -1631,8 +1633,8 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
rq->nr_phys_segments = rq_src->nr_phys_segments;
rq->ioprio = rq_src->ioprio;
- if (rq->bio)
- blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask);
+ if (rq->bio && blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask) < 0)
+ goto free_and_out;
return 0;