diff mbox series

[2/2] mm: avoid unnecessary swap_info_struct allocation

Message ID a24bf353-8715-2bee-d0fa-96ca06c5b69f@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series [1/2] mm: use kvzalloc for swap_info_struct allocation | expand

Commit Message

Vasily Averin Nov. 4, 2018, 10:13 p.m. UTC
Currently newly allocated swap_info_struct can be quickly freed.
This patch avoid uneccessary high-order page allocation and helps
to decrease the memory pressure.

Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
---
 mm/swapfile.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

Comments

Huang, Ying Nov. 5, 2018, 12:57 a.m. UTC | #1
Vasily Averin <vvs@virtuozzo.com> writes:

> Currently newly allocated swap_info_struct can be quickly freed.
> This patch avoid uneccessary high-order page allocation and helps
> to decrease the memory pressure.

I think swapon/swapoff are rare operations, so it will not increase the
memory pressure much.  

Best Regards,
Huang, Ying

> Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
> ---
>  mm/swapfile.c | 18 +++++++++++++-----
>  1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 8688ae65ef58..53ec2f0cdf26 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -2809,14 +2809,17 @@ late_initcall(max_swapfiles_check);
>  
>  static struct swap_info_struct *alloc_swap_info(void)
>  {
> -	struct swap_info_struct *p;
> +	struct swap_info_struct *p = NULL;
>  	unsigned int type;
>  	int i;
> +	bool force_alloc = false;
>  
> -	p = kvzalloc(sizeof(*p), GFP_KERNEL);
> -	if (!p)
> -		return ERR_PTR(-ENOMEM);
> -
> +retry:
> +	if (force_alloc) {
> +		p = kvzalloc(sizeof(*p), GFP_KERNEL);
> +		if (!p)
> +			return ERR_PTR(-ENOMEM);
> +	}
>  	spin_lock(&swap_lock);
>  	for (type = 0; type < nr_swapfiles; type++) {
>  		if (!(swap_info[type]->flags & SWP_USED))
> @@ -2828,6 +2831,11 @@ static struct swap_info_struct *alloc_swap_info(void)
>  		return ERR_PTR(-EPERM);
>  	}
>  	if (type >= nr_swapfiles) {
> +		if (!force_alloc) {
> +			force_alloc = true;
> +			spin_unlock(&swap_lock);
> +			goto retry;
> +		}
>  		p->type = type;
>  		swap_info[type] = p;
>  		/*
Vasily Averin Nov. 5, 2018, 5:19 a.m. UTC | #2
On 11/5/18 3:57 AM, Huang, Ying wrote:
> Vasily Averin <vvs@virtuozzo.com> writes:
> 
>> Currently newly allocated swap_info_struct can be quickly freed.
>> This patch avoid uneccessary high-order page allocation and helps
>> to decrease the memory pressure.
> 
> I think swapon/swapoff are rare operations, so it will not increase the
> memory pressure much.

You are right, typically it should not affect usual nodes.

It's OpenVz-specific usecase.

OpenVz allows hosters to run hundreds of non-trusted containers per node.
Our containers have enabled "virtual swap" functionality, 
and container's owners can call sys_swapon without any limits.
Containers can be restarted in any time and we would like to 
decrease number of unnecessary high-order memory allocations.

>> Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
>> ---
>>  mm/swapfile.c | 18 +++++++++++++-----
>>  1 file changed, 13 insertions(+), 5 deletions(-)
>>
>> diff --git a/mm/swapfile.c b/mm/swapfile.c
>> index 8688ae65ef58..53ec2f0cdf26 100644
>> --- a/mm/swapfile.c
>> +++ b/mm/swapfile.c
>> @@ -2809,14 +2809,17 @@ late_initcall(max_swapfiles_check);
>>  
>>  static struct swap_info_struct *alloc_swap_info(void)
>>  {
>> -	struct swap_info_struct *p;
>> +	struct swap_info_struct *p = NULL;
>>  	unsigned int type;
>>  	int i;
>> +	bool force_alloc = false;
>>  
>> -	p = kvzalloc(sizeof(*p), GFP_KERNEL);
>> -	if (!p)
>> -		return ERR_PTR(-ENOMEM);
>> -
>> +retry:
>> +	if (force_alloc) {
>> +		p = kvzalloc(sizeof(*p), GFP_KERNEL);
>> +		if (!p)
>> +			return ERR_PTR(-ENOMEM);
>> +	}
>>  	spin_lock(&swap_lock);
>>  	for (type = 0; type < nr_swapfiles; type++) {
>>  		if (!(swap_info[type]->flags & SWP_USED))
>> @@ -2828,6 +2831,11 @@ static struct swap_info_struct *alloc_swap_info(void)
>>  		return ERR_PTR(-EPERM);
>>  	}
>>  	if (type >= nr_swapfiles) {
>> +		if (!force_alloc) {
>> +			force_alloc = true;
>> +			spin_unlock(&swap_lock);
>> +			goto retry;
>> +		}
>>  		p->type = type;
>>  		swap_info[type] = p;
>>  		/*
>
Vasily Averin Nov. 5, 2018, 10:41 a.m. UTC | #3
I was wrong, openVz blocks sys_swapon/swapoff syscalls inside containers.
Our kernel just emulates /proc/swaps output inside containers,
it is enough for 'swapon' userspace to do not fail and show required info.

So I do not have any special arguments for proposed patch.

On 11/5/18 8:19 AM, Vasily Averin wrote:
> On 11/5/18 3:57 AM, Huang, Ying wrote:
>> Vasily Averin <vvs@virtuozzo.com> writes:
>>
>>> Currently newly allocated swap_info_struct can be quickly freed.
>>> This patch avoid uneccessary high-order page allocation and helps
>>> to decrease the memory pressure.
>>
>> I think swapon/swapoff are rare operations, so it will not increase the
>> memory pressure much.
> 
> You are right, typically it should not affect usual nodes.
> 
> It's OpenVz-specific usecase.
> 
> OpenVz allows hosters to run hundreds of non-trusted containers per node.
> Our containers have enabled "virtual swap" functionality, 
> and container's owners can call sys_swapon without any limits.
> Containers can be restarted in any time and we would like to 
> decrease number of unnecessary high-order memory allocations.
> 
>>> Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
>>> ---
>>>  mm/swapfile.c | 18 +++++++++++++-----
>>>  1 file changed, 13 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/mm/swapfile.c b/mm/swapfile.c
>>> index 8688ae65ef58..53ec2f0cdf26 100644
>>> --- a/mm/swapfile.c
>>> +++ b/mm/swapfile.c
>>> @@ -2809,14 +2809,17 @@ late_initcall(max_swapfiles_check);
>>>  
>>>  static struct swap_info_struct *alloc_swap_info(void)
>>>  {
>>> -	struct swap_info_struct *p;
>>> +	struct swap_info_struct *p = NULL;
>>>  	unsigned int type;
>>>  	int i;
>>> +	bool force_alloc = false;
>>>  
>>> -	p = kvzalloc(sizeof(*p), GFP_KERNEL);
>>> -	if (!p)
>>> -		return ERR_PTR(-ENOMEM);
>>> -
>>> +retry:
>>> +	if (force_alloc) {
>>> +		p = kvzalloc(sizeof(*p), GFP_KERNEL);
>>> +		if (!p)
>>> +			return ERR_PTR(-ENOMEM);
>>> +	}
>>>  	spin_lock(&swap_lock);
>>>  	for (type = 0; type < nr_swapfiles; type++) {
>>>  		if (!(swap_info[type]->flags & SWP_USED))
>>> @@ -2828,6 +2831,11 @@ static struct swap_info_struct *alloc_swap_info(void)
>>>  		return ERR_PTR(-EPERM);
>>>  	}
>>>  	if (type >= nr_swapfiles) {
>>> +		if (!force_alloc) {
>>> +			force_alloc = true;
>>> +			spin_unlock(&swap_lock);
>>> +			goto retry;
>>> +		}
>>>  		p->type = type;
>>>  		swap_info[type] = p;
>>>  		/*
>>
diff mbox series

Patch

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 8688ae65ef58..53ec2f0cdf26 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2809,14 +2809,17 @@  late_initcall(max_swapfiles_check);
 
 static struct swap_info_struct *alloc_swap_info(void)
 {
-	struct swap_info_struct *p;
+	struct swap_info_struct *p = NULL;
 	unsigned int type;
 	int i;
+	bool force_alloc = false;
 
-	p = kvzalloc(sizeof(*p), GFP_KERNEL);
-	if (!p)
-		return ERR_PTR(-ENOMEM);
-
+retry:
+	if (force_alloc) {
+		p = kvzalloc(sizeof(*p), GFP_KERNEL);
+		if (!p)
+			return ERR_PTR(-ENOMEM);
+	}
 	spin_lock(&swap_lock);
 	for (type = 0; type < nr_swapfiles; type++) {
 		if (!(swap_info[type]->flags & SWP_USED))
@@ -2828,6 +2831,11 @@  static struct swap_info_struct *alloc_swap_info(void)
 		return ERR_PTR(-EPERM);
 	}
 	if (type >= nr_swapfiles) {
+		if (!force_alloc) {
+			force_alloc = true;
+			spin_unlock(&swap_lock);
+			goto retry;
+		}
 		p->type = type;
 		swap_info[type] = p;
 		/*