Skip to content

Commit 5f9d1fd

Browse files
committed
raid5: fix memory leak of bio integrity data
Yi reported a memory leak of raid5 with DIF/DIX enabled disks. raid5 doesn't alloc/free bio, instead it reuses bios. There are two issues in current code: 1. the code calls bio_init (from init_stripe->raid5_build_block->bio_init) then bio_reset (ops_run_io). The bio is reused, so likely there is integrity data attached. bio_init will clear a pointer to integrity data and makes bio_reset can't release the data 2. bio_reset is called before dispatching bio. After bio is finished, it's possible we don't free bio's integrity data (eg, we don't call bio_reset again) Both issues will cause memory leak. The patch moves bio_init to stripe creation and bio_reset to bio end io. This will fix the two issues. Reported-by: Yi Zhang <[email protected]> Signed-off-by: Shaohua Li <[email protected]>
1 parent 2702862 commit 5f9d1fd

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

drivers/md/raid5.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,6 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
10051005

10061006
set_bit(STRIPE_IO_STARTED, &sh->state);
10071007

1008-
bio_reset(bi);
10091008
bi->bi_bdev = rdev->bdev;
10101009
bio_set_op_attrs(bi, op, op_flags);
10111010
bi->bi_end_io = op_is_write(op)
@@ -1057,7 +1056,6 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
10571056

10581057
set_bit(STRIPE_IO_STARTED, &sh->state);
10591058

1060-
bio_reset(rbi);
10611059
rbi->bi_bdev = rrdev->bdev;
10621060
bio_set_op_attrs(rbi, op, op_flags);
10631061
BUG_ON(!op_is_write(op));
@@ -1990,9 +1988,11 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
19901988
put_cpu();
19911989
}
19921990

1993-
static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp)
1991+
static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp,
1992+
int disks)
19941993
{
19951994
struct stripe_head *sh;
1995+
int i;
19961996

19971997
sh = kmem_cache_zalloc(sc, gfp);
19981998
if (sh) {
@@ -2001,14 +2001,20 @@ static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp)
20012001
INIT_LIST_HEAD(&sh->batch_list);
20022002
INIT_LIST_HEAD(&sh->lru);
20032003
atomic_set(&sh->count, 1);
2004+
for (i = 0; i < disks; i++) {
2005+
struct r5dev *dev = &sh->dev[i];
2006+
2007+
bio_init(&dev->req);
2008+
bio_init(&dev->rreq);
2009+
}
20042010
}
20052011
return sh;
20062012
}
20072013
static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
20082014
{
20092015
struct stripe_head *sh;
20102016

2011-
sh = alloc_stripe(conf->slab_cache, gfp);
2017+
sh = alloc_stripe(conf->slab_cache, gfp, conf->pool_size);
20122018
if (!sh)
20132019
return 0;
20142020

@@ -2179,7 +2185,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
21792185
mutex_lock(&conf->cache_size_mutex);
21802186

21812187
for (i = conf->max_nr_stripes; i; i--) {
2182-
nsh = alloc_stripe(sc, GFP_KERNEL);
2188+
nsh = alloc_stripe(sc, GFP_KERNEL, newsize);
21832189
if (!nsh)
21842190
break;
21852191

@@ -2311,6 +2317,7 @@ static void raid5_end_read_request(struct bio * bi)
23112317
(unsigned long long)sh->sector, i, atomic_read(&sh->count),
23122318
bi->bi_error);
23132319
if (i == disks) {
2320+
bio_reset(bi);
23142321
BUG();
23152322
return;
23162323
}
@@ -2414,6 +2421,7 @@ static void raid5_end_read_request(struct bio * bi)
24142421
clear_bit(R5_LOCKED, &sh->dev[i].flags);
24152422
set_bit(STRIPE_HANDLE, &sh->state);
24162423
raid5_release_stripe(sh);
2424+
bio_reset(bi);
24172425
}
24182426

24192427
static void raid5_end_write_request(struct bio *bi)
@@ -2448,6 +2456,7 @@ static void raid5_end_write_request(struct bio *bi)
24482456
(unsigned long long)sh->sector, i, atomic_read(&sh->count),
24492457
bi->bi_error);
24502458
if (i == disks) {
2459+
bio_reset(bi);
24512460
BUG();
24522461
return;
24532462
}
@@ -2491,18 +2500,17 @@ static void raid5_end_write_request(struct bio *bi)
24912500

24922501
if (sh->batch_head && sh != sh->batch_head)
24932502
raid5_release_stripe(sh->batch_head);
2503+
bio_reset(bi);
24942504
}
24952505

24962506
static void raid5_build_block(struct stripe_head *sh, int i, int previous)
24972507
{
24982508
struct r5dev *dev = &sh->dev[i];
24992509

2500-
bio_init(&dev->req);
25012510
dev->req.bi_io_vec = &dev->vec;
25022511
dev->req.bi_max_vecs = 1;
25032512
dev->req.bi_private = sh;
25042513

2505-
bio_init(&dev->rreq);
25062514
dev->rreq.bi_io_vec = &dev->rvec;
25072515
dev->rreq.bi_max_vecs = 1;
25082516
dev->rreq.bi_private = sh;

0 commit comments

Comments
 (0)