diff options
author | Eric Biggers <ebiggers@google.com> | 2020-09-15 20:53:14 -0700 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-10-05 10:47:43 -0600 |
commit | 93f221ae08381e994ac9f9ff6aa743e612e49718 (patch) | |
tree | fe3f7bb6254559fb0d7a84fc467389a5af30c821 /block/blk-core.c | |
parent | 07560151db960d26b425410d6fd778e6757a5da2 (diff) | |
download | linux-stable-93f221ae08381e994ac9f9ff6aa743e612e49718.tar.gz linux-stable-93f221ae08381e994ac9f9ff6aa743e612e49718.tar.bz2 linux-stable-93f221ae08381e994ac9f9ff6aa743e612e49718.zip |
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.c | 8 |
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; |