Recent 3.x kernels: Memory leak causing OOMs
Catalin Marinas
catalin.marinas at arm.com
Tue Apr 1 08:58:17 PDT 2014
On Tue, Apr 01, 2014 at 12:38:51PM +0100, Russell King - ARM Linux wrote:
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index aacf6bf352d8..604bad2fa442 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -123,8 +123,14 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
> bio = r1_bio->bios[j];
> bio->bi_vcnt = RESYNC_PAGES;
>
> - if (bio_alloc_pages(bio, gfp_flags))
> - goto out_free_bio;
> + if (bio_alloc_pages(bio, gfp_flags)) {
> + /*
> + * Mark this as having no pages - bio_alloc_pages
> + * removes any it allocated.
> + */
> + bio->bi_vcnt = 0;
> + goto out_free_all_bios;
> + }
> }
> /* If not user-requests, copy the page pointers to all bios */
> if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
> @@ -138,9 +144,25 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
>
> return r1_bio;
>
> +out_free_all_bios:
> + j = -1;
> out_free_bio:
> - while (++j < pi->raid_disks)
> - bio_put(r1_bio->bios[j]);
> + while (++j < pi->raid_disks) {
> + bio = r1_bio->bios[j];
> + if (bio->bi_vcnt) {
> + struct bio_vec *bv;
> + int i;
> + /*
> + * Annoyingly, BIO has no way to do this, so we have
> + * to do it manually. Given the trouble here, and
> + * the lack of BIO support for cleaning up, I don't
> + * care about linux/bio.h's comment about this helper.
> + */
> + bio_for_each_segment_all(bv, bio, i)
> + __free_page(bv->bv_page);
> + }
Do you still need the 'if' block here? bio_for_each_segment_all() checks
for bio->bi_vcnt which was set to 0 above.
--
Catalin
More information about the linux-arm-kernel
mailing list