[rh7] : fs/pipe: Use kvmalloc for pipe buffers

Submitted by Kirill Gorkunov on Feb. 13, 2018, 8:17 a.m.

Details

Message ID 20180213081738.GA32380@uranus.lan
State New
Series ": fs/pipe: Use kvmalloc for pipe buffers"
Headers show

Commit Message

Kirill Gorkunov Feb. 13, 2018, 8:17 a.m.
To restore big slabs of memory (more than 1G) via pipes we need
pipes to be able to carry such sizes, for this sake Andrey propose
to use kvmalloc calls. Looking into the code I didn't find a reason
why we can't do so, thus here is a patch.

https://jira.sw.ru/browse/PSBM-69201

CC: Andrey Vagin <avagin@virtuozzo.com>
CC: Andrey Ryabinin <aryabinin@virtuozzo.com>
CC: Konstantin Khorenko <khorenko@virtuozzo.com>
CC: "Denis V. Lunev" <den@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
---
Note I wrapped the calls with CONFIG_VE for a while.

 fs/pipe.c |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Patch hide | download patch | download mbox

Index: linux-pcs7.git/fs/pipe.c
===================================================================
--- linux-pcs7.git.orig/fs/pipe.c
+++ linux-pcs7.git/fs/pipe.c
@@ -845,7 +845,11 @@  struct pipe_inode_info *alloc_pipe_info(
 		if (!too_many_pipe_buffers_hard(user)) {
 			if (too_many_pipe_buffers_soft(user))
 				pipe_bufs = 1;
+#ifdef CONFIG_VE
+			pipe->bufs = kvmalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL | __GFP_ZERO);
+#else
 			pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+#endif
 		}
 
 		if (pipe->bufs) {
@@ -877,7 +881,11 @@  void free_pipe_info(struct pipe_inode_in
 	}
 	if (pipe->tmp_page)
 		__free_page(pipe->tmp_page);
+#ifdef CONFIG_VE
+	kvfree(pipe->bufs);
+#else
 	kfree(pipe->bufs);
+#endif
 	kfree(pipe);
 }
 
@@ -1235,7 +1243,11 @@  static long pipe_set_size(struct pipe_in
 	if (nr_pages < pipe->nrbufs)
 		return -EBUSY;
 
+#ifdef CONFIG_VE
+	bufs = kvmalloc(nr_pages * sizeof(*bufs), GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
+#else
 	bufs = kcalloc(nr_pages, sizeof(*bufs), GFP_KERNEL | __GFP_NOWARN);
+#endif
 	if (unlikely(!bufs))
 		return -ENOMEM;
 
@@ -1262,7 +1274,11 @@  static long pipe_set_size(struct pipe_in
 
 	account_pipe_buffers(pipe, pipe->buffers, nr_pages);
 	pipe->curbuf = 0;
+#ifdef CONFIG_VE
+	kvfree(pipe->bufs);
+#else
 	kfree(pipe->bufs);
+#endif
 	pipe->bufs = bufs;
 	pipe->buffers = nr_pages;
 	return nr_pages * PAGE_SIZE;

Comments

Konstantin Khorenko Feb. 14, 2018, 10:39 a.m.
On 02/13/2018 11:17 AM, Cyrill Gorcunov wrote:
> To restore big slabs of memory (more than 1G) via pipes we need
> pipes to be able to carry such sizes, for this sake Andrey propose
> to use kvmalloc calls. Looking into the code I didn't find a reason
> why we can't do so, thus here is a patch.
>
> https://jira.sw.ru/browse/PSBM-69201
>
> CC: Andrey Vagin <avagin@virtuozzo.com>
> CC: Andrey Ryabinin <aryabinin@virtuozzo.com>
> CC: Konstantin Khorenko <khorenko@virtuozzo.com>
> CC: "Denis V. Lunev" <den@virtuozzo.com>
> Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
> ---
> Note I wrapped the calls with CONFIG_VE for a while.

Note, i dropped ifdef CONFIG_VE wrappers.

>
>  fs/pipe.c |   16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> Index: linux-pcs7.git/fs/pipe.c
> ===================================================================
> --- linux-pcs7.git.orig/fs/pipe.c
> +++ linux-pcs7.git/fs/pipe.c
> @@ -845,7 +845,11 @@ struct pipe_inode_info *alloc_pipe_info(
>  		if (!too_many_pipe_buffers_hard(user)) {
>  			if (too_many_pipe_buffers_soft(user))
>  				pipe_bufs = 1;
> +#ifdef CONFIG_VE
> +			pipe->bufs = kvmalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL | __GFP_ZERO);
> +#else
>  			pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
> +#endif
>  		}
>
>  		if (pipe->bufs) {
> @@ -877,7 +881,11 @@ void free_pipe_info(struct pipe_inode_in
>  	}
>  	if (pipe->tmp_page)
>  		__free_page(pipe->tmp_page);
> +#ifdef CONFIG_VE
> +	kvfree(pipe->bufs);
> +#else
>  	kfree(pipe->bufs);
> +#endif
>  	kfree(pipe);
>  }
>
> @@ -1235,7 +1243,11 @@ static long pipe_set_size(struct pipe_in
>  	if (nr_pages < pipe->nrbufs)
>  		return -EBUSY;
>
> +#ifdef CONFIG_VE
> +	bufs = kvmalloc(nr_pages * sizeof(*bufs), GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
> +#else
>  	bufs = kcalloc(nr_pages, sizeof(*bufs), GFP_KERNEL | __GFP_NOWARN);
> +#endif
>  	if (unlikely(!bufs))
>  		return -ENOMEM;
>
> @@ -1262,7 +1274,11 @@ static long pipe_set_size(struct pipe_in
>
>  	account_pipe_buffers(pipe, pipe->buffers, nr_pages);
>  	pipe->curbuf = 0;
> +#ifdef CONFIG_VE
> +	kvfree(pipe->bufs);
> +#else
>  	kfree(pipe->bufs);
> +#endif
>  	pipe->bufs = bufs;
>  	pipe->buffers = nr_pages;
>  	return nr_pages * PAGE_SIZE;
> .
>