> -----Original Message----- > From: Jason Wang [mailto:jasowang@xxxxxxxxxx] > Sent: Monday, November 24, 2014 15:28 PM > To: Dexuan Cui; gregkh@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; > driverdev-devel@xxxxxxxxxxxxxxxxxxxxxx; olaf@xxxxxxxxx; > apw@xxxxxxxxxxxxx; KY Srinivasan > Cc: Haiyang Zhang > Subject: Re: [PATCH] hv: hv_balloon: avoid memory leak on alloc_error of > 2MB memory block > > On 11/24/2014 02:08 PM, Dexuan Cui wrote: > >> -----Original Message----- > >> > From: Jason Wang [mailto:jasowang@xxxxxxxxxx] > >> > Sent: Monday, November 24, 2014 13:18 PM > >> > To: Dexuan Cui; gregkh@xxxxxxxxxxxxxxxxxxx; linux- > kernel@xxxxxxxxxxxxxxx; > >> > driverdev-devel@xxxxxxxxxxxxxxxxxxxxxx; olaf@xxxxxxxxx; > >> > apw@xxxxxxxxxxxxx; KY Srinivasan > >> > Cc: Haiyang Zhang > >> > Subject: Re: [PATCH] hv: hv_balloon: avoid memory leak on > alloc_error of > >> > 2MB memory block > >> > > >> > On 11/24/2014 01:56 PM, Dexuan Cui wrote: > >>> > > If num_ballooned is not 0, we shouldn't neglect the already- > allocated > >> > 2MB > >>> > > memory block(s). > >>> > > > >>> > > Cc: K. Y. Srinivasan <kys@xxxxxxxxxxxxx> > >>> > > Cc: <stable@xxxxxxxxxxxxxxx> > >>> > > Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx> > >>> > > --- > >>> > > drivers/hv/hv_balloon.c | 4 +++- > >>> > > 1 file changed, 3 insertions(+), 1 deletion(-) > >>> > > > >>> > > diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c > >>> > > index 5e90c5d..cba2d3b 100644 > >>> > > --- a/drivers/hv/hv_balloon.c > >>> > > +++ b/drivers/hv/hv_balloon.c > >>> > > @@ -1091,6 +1091,8 @@ static void balloon_up(struct > work_struct > >> > *dummy) > >>> > > bool done = false; > >>> > > int i; > >>> > > > >>> > > + /* The host does balloon_up in 2MB. */ > >>> > > + WARN_ON(num_pages % PAGES_IN_2M != 0); > >>> > > > >>> > > /* > >>> > > * We will attempt 2M allocations. However, if we fail to > >>> > > @@ -1111,7 +1113,7 @@ static void balloon_up(struct > work_struct > >> > *dummy) > >>> > > bl_resp, alloc_unit, > >>> > > &alloc_error); > >>> > > > >>> > > - if ((alloc_error) && (alloc_unit != 1)) { > >>> > > + if (alloc_error && (alloc_unit != 1) && > num_ballooned == 0) > >> > { > >>> > > alloc_unit = 1; > >>> > > continue; > >>> > > } > >> > > >> > Before the change, we may retry the 4K allocation when part or all 2M > >> > allocations were failed. This makes sense when memory is fragmented. > But > > Yes, but all the partially-allocated 2MB memory blocks are lost(mem leak). > > > >> > after the change, if part of 2M allocation were failed, we won't retry > >> > 4K allocation. Is this expected? > > Hi Jason, > > The patch doesn't break the "try 2MB first; then try 4K" logic: > > > > With the change, we'll retry the 2MB allocation in the next iteration of the > > same while (!done) loop -- we expect this retry will cause > > "alloc_error && (alloc_unit != 1) && num_ballooned == 0" to be true, > > so we'll later try 4K allocation, as we did before. > > If I read the code correctly, if part of 2M allocation fails. > alloc_balloon_pages() will have a non zero return value with alloc_error > set. Then it will match the following check: > > if ((alloc_error) || (num_ballooned == num_pages)) > { > > which will set done to true. So there's no second iteration of while > (!done) loop? Oh... I see the issue in my patch. Thanks for pointing this out, Jason! > Probably you need something like: > > if ((alloc_unit != 1) && (num_ballooned == 0)) { > alloc_unit = 1; > continue; > } > > if ((alloc_unit == 1) || (num_ballooned == num_pages)) { > ... > } Your code is good, except for one thing: alloc_balloon_pages() can return due to: if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) > PAGE_SIZE) return i * alloc_unit; In this case, "alloc_unit == 1" is true, but we shouldn't run "done = true". How do you like this? I made a few changes based on your code. @@ -1086,16 +1088,18 @@ static void balloon_up(struct work_struct *dummy) num_pages -= num_ballooned; + alloc_error = false; num_ballooned = alloc_balloon_pages(&dm_device, num_pages, bl_resp, alloc_unit, &alloc_error); - if ((alloc_error) && (alloc_unit != 1)) { + if (alloc_unit != 1 && num_ballooned == 0) { alloc_unit = 1; continue; } - if ((alloc_error) || (num_ballooned == num_pages)) { + if ((alloc_unit == 1 && alloc_error) || + (num_ballooned == num_pages)) { bl_resp->more_pages = 0; done = true; dm_device.state = DM_INITIALIZED; If you're Ok with this, I'll send out a v2 patch. Thanks, -- Dexuan _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel