Skip to content

Commit 9ae3b3f

Browse files
committed
block: provide bio_uninit() free freeing integrity/task associations
Wen reports significant memory leaks with DIF and O_DIRECT: "With nvme devive + T10 enabled, On a system it has 256GB and started logging /proc/meminfo & /proc/slabinfo for every minute and in an hour it increased by 15968128 kB or ~15+GB.. Approximately 256 MB / minute leaking. /proc/meminfo | grep SUnreclaim... SUnreclaim: 6752128 kB SUnreclaim: 6874880 kB SUnreclaim: 7238080 kB .... SUnreclaim: 22307264 kB SUnreclaim: 22485888 kB SUnreclaim: 22720256 kB When testcases with T10 enabled call into __blkdev_direct_IO_simple, code doesn't free memory allocated by bio_integrity_alloc. The patch fixes the issue. HTX has been run with +60 hours without failure." Since __blkdev_direct_IO_simple() allocates the bio on the stack, it doesn't go through the regular bio free. This means that any ancillary data allocated with the bio through the stack is not freed. Hence, we can leak the integrity data associated with the bio, if the device is using DIF/DIX. Fix this by providing a bio_uninit() and export it, so that we can use it to free this data. Note that this is a minimal fix for this issue. Any current user of bio's that are allocated outside of bio_alloc_bioset() suffers from this issue, most notably some drivers. We will fix those in a more comprehensive patch for 4.13. This also means that the commit marked as being fixed by this isn't the real culprit, it's just the most obvious one out there. Fixes: 542ff7b ("block: new direct I/O implementation") Reported-by: Wen Xiong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent ebef736 commit 9ae3b3f

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

block/bio.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,20 +240,21 @@ struct bio_vec *bvec_alloc(gfp_t gfp_mask, int nr, unsigned long *idx,
240240
return bvl;
241241
}
242242

243-
static void __bio_free(struct bio *bio)
243+
void bio_uninit(struct bio *bio)
244244
{
245245
bio_disassociate_task(bio);
246246

247247
if (bio_integrity(bio))
248248
bio_integrity_free(bio);
249249
}
250+
EXPORT_SYMBOL(bio_uninit);
250251

251252
static void bio_free(struct bio *bio)
252253
{
253254
struct bio_set *bs = bio->bi_pool;
254255
void *p;
255256

256-
__bio_free(bio);
257+
bio_uninit(bio);
257258

258259
if (bs) {
259260
bvec_free(bs->bvec_pool, bio->bi_io_vec, BVEC_POOL_IDX(bio));
@@ -271,6 +272,11 @@ static void bio_free(struct bio *bio)
271272
}
272273
}
273274

275+
/*
276+
* Users of this function have their own bio allocation. Subsequently,
277+
* they must remember to pair any call to bio_init() with bio_uninit()
278+
* when IO has completed, or when the bio is released.
279+
*/
274280
void bio_init(struct bio *bio, struct bio_vec *table,
275281
unsigned short max_vecs)
276282
{
@@ -297,7 +303,7 @@ void bio_reset(struct bio *bio)
297303
{
298304
unsigned long flags = bio->bi_flags & (~0UL << BIO_RESET_BITS);
299305

300-
__bio_free(bio);
306+
bio_uninit(bio);
301307

302308
memset(bio, 0, BIO_RESET_BYTES);
303309
bio->bi_flags = flags;

fs/block_dev.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
263263
kfree(vecs);
264264

265265
if (unlikely(bio.bi_error))
266-
return bio.bi_error;
266+
ret = bio.bi_error;
267+
268+
bio_uninit(&bio);
269+
267270
return ret;
268271
}
269272

include/linux/bio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ extern void bio_advance(struct bio *, unsigned);
426426

427427
extern void bio_init(struct bio *bio, struct bio_vec *table,
428428
unsigned short max_vecs);
429+
extern void bio_uninit(struct bio *);
429430
extern void bio_reset(struct bio *);
430431
void bio_chain(struct bio *, struct bio *);
431432

0 commit comments

Comments
 (0)