diff options
author | Christoph Hellwig <hch@lst.de> | 2024-07-02 18:10:21 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-09-12 12:12:59 +0300 |
commit | 64149da0fddbbfe43e11c0348d8c8b4171dae3a2 (patch) | |
tree | 6978023ce38e1f55318917556e63a91452938919 /block | |
parent | 08205763198a7e04a1357b4c51ddeab80628da00 (diff) | |
download | linux-64149da0fddbbfe43e11c0348d8c8b4171dae3a2.tar.xz |
block: don't call bio_uninit from bio_endio
[ Upstream commit bf4c89fc8797f5c0964a0c3d561fbe7e8483b62f ]
Commit b222dd2fdd53 ("block: call bio_uninit in bio_endio") added a call
to bio_uninit in bio_endio to work around callers that use bio_init but
fail to call bio_uninit after they are done to release the resources.
While this is an abuse of the bio_init API we still have quite a few of
those left. But this early uninit causes a problem for integrity data,
as at least some users need the bio_integrity_payload. Right now the
only one is the NVMe passthrough which archives this by adding a special
case to skip the freeing if the BIP_INTEGRITY_USER flag is set.
Sort this out by only putting bi_blkg in bio_endio as that is the cause
of the actual leaks - the few users of the crypto context and integrity
data all properly call bio_uninit, usually through bio_put for
dynamically allocated bios.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20240702151047.1746127-4-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/bio.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/block/bio.c b/block/bio.c index e9e809a63c59..c7a4bc05c43e 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1630,8 +1630,18 @@ again: goto again; } - /* release cgroup info */ - bio_uninit(bio); +#ifdef CONFIG_BLK_CGROUP + /* + * Release cgroup info. We shouldn't have to do this here, but quite + * a few callers of bio_init fail to call bio_uninit, so we cover up + * for that here at least for now. + */ + if (bio->bi_blkg) { + blkg_put(bio->bi_blkg); + bio->bi_blkg = NULL; + } +#endif + if (bio->bi_end_io) bio->bi_end_io(bio); } |