[CRIU] Re: [PATCH cr] restore: optimize restorer_get_vma_hint

avagin at gmail.com avagin at gmail.com
Sat Apr 7 10:21:27 EDT 2012


On 04/07/2012 12:18 PM, Cyrill Gorcunov wrote:
> On Sat, Apr 07, 2012 at 11:09:29AM +0400, Andrey Vagin wrote:
>> It's an O(n) algorithm.
>>
>> Now we iterate both lists simultaneously to find a hole.
>>
>> Signed-off-by: Andrey Vagin<avagin at openvz.org>
>> ---
>>   cr-restore.c |   49 ++++++++++++++++++++++++++++++++-----------------
>>   1 files changed, 32 insertions(+), 17 deletions(-)
>>
>> diff --git a/cr-restore.c b/cr-restore.c
>> index 2162fc1..8405336 100644
>> --- a/cr-restore.c
>> +++ b/cr-restore.c
>> @@ -870,39 +870,54 @@ static int restore_all_tasks(pid_t pid, struct cr_options *opts)
>>   	return restore_root_task(pid, opts);
>>   }
>>
>> +#define TASK_SIZE_MAX   ((1UL<<  47) - PAGE_SIZE)
>>   static long restorer_get_vma_hint(pid_t pid, struct list_head *tgt_vma_list,
>>   		struct list_head *self_vma_list, long vma_len)
>>   {
>> -	struct vma_area *t_vma;
>> +	struct vma_area *t_vma, *s_vma;
>>   	long prev_vma_end = 0;
>> +	struct vma_area end_vma;
>> +
>> +	end_vma.vma.start = end_vma.vma.end = TASK_SIZE_MAX;
>> +	prev_vma_end = PAGE_SIZE;
>>
>>   	/*
>>   	 * Here we need some heuristics -- the VMA which restorer will
>>   	 * belong to should not be unmapped, so we need to gueess out
>>   	 * where to put it in.
>> -	 *
>> -	 * Yes, I know it's an O(n^2) algorithm, but usually there are
>> -	 * not that many VMAs presented so instead of consuming memory
>> -	 * better to stick with it.
>>   	 */
>>
>> -	list_for_each_entry(t_vma, tgt_vma_list, list) {
>> -		if (prev_vma_end&&  ((t_vma->vma.start - prev_vma_end)>  vma_len)) {
>> -			struct vma_area *s_vma;
>> -			unsigned long prev_vma_end2 = 0;
>> +	s_vma = list_first_entry(self_vma_list, struct vma_area, list);
>> +	t_vma = list_first_entry(tgt_vma_list, struct vma_area, list);
>>
>> -			list_for_each_entry(s_vma, self_vma_list, list) {
>> -				if (prev_vma_end2 + vma_len>  t_vma->vma.start)
>> -					break;
>> -				if (prev_vma_end2&&  (prev_vma_end2>= prev_vma_end)&&
>> -				    ((s_vma->vma.start - prev_vma_end2)>  vma_len))
>> -					return prev_vma_end2;
>> +	while (1) {
>> +		if (prev_vma_end + vma_len>  s_vma->vma.start) {
>> +			if (s_vma->list.next == self_vma_list) {
>> +				s_vma =&end_vma;
>
> If s_vma is the last one on self_vma_list you could break immediately, no?
No, because s_vma points on vma after the hole.
>
> And the snippet I somehow miss is -- how the situation handled when
>
>                hole
>              a      b
> source |----|      |-----|
> target   |----|      |-----|
>                c      d
>
> the hole fits the requested size but the hole is shifted
> in target, so that you've
>
> 	prev_vma_end = a
>
> and then you find that a - d>  vma_len and return a
> as start address for new mapping while finally it
> might intersect with address c.

Look at "continue" one more time.
prev_vma_end is returned only if both condition are true

if (prev_vma_end + vma_len > s_vma->vma.start) {
....
if (prev_vma_end + vma_len > t_vma->vma.start) {
...

>
> Or I miss something obvious?
>
> 	Cyrill



More information about the CRIU mailing list