[RHEL7,COMMIT] fs/fuse/dev: improve ->splice() with fragmented memory

Submitted by Konstantin Khorenko on Dec. 7, 2017, 10:57 a.m.

Details

Message ID 201712071057.vB7AvoKI031240@finist_ce7.work
State New
Series "fs/fuse/dev: improve ->splice() with fragmented memory"
Headers show

Commit Message

Konstantin Khorenko Dec. 7, 2017, 10:57 a.m.
The commit is pushed to "branch-rh7-3.10.0-693.11.1.vz7.39.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.11.1.vz7.39.1
------>
commit fe4b25ff272f8e5143d8f8223dac2a8577ceb937
Author: Andrey Ryabinin <aryabinin@virtuozzo.com>
Date:   Thu Dec 7 13:57:49 2017 +0300

    fs/fuse/dev: improve ->splice() with fragmented memory
    
    fuse_dev_splice_[read,write]() temporary allocates array of pipe_buffer
    structs. Depending on pipe size it could be quite large, thus we stall
    in high order allocation request. Use kvmalloc() instead of kmalloc()
    to fallback in vmalloc() if high order page is not available at the moment.
    
    https://jira.sw.ru/browse/PSBM-77949
    Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 fs/fuse/dev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 7d74782c6f43..9e77e198de60 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1354,7 +1354,7 @@  static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
 	if (!fud)
 		return -EPERM;
 
-	bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+	bufs = kvmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
 	if (!bufs)
 		return -ENOMEM;
 
@@ -1411,7 +1411,7 @@  static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
 	for (; page_nr < cs.nr_segs; page_nr++)
 		page_cache_release(bufs[page_nr].page);
 
-	kfree(bufs);
+	kvfree(bufs);
 	return ret;
 }
 
@@ -1992,7 +1992,7 @@  static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 	if (!fud)
 		return -EPERM;
 
-	bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+	bufs = kvmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
 	if (!bufs)
 		return -ENOMEM;
 
@@ -2050,7 +2050,7 @@  static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 		buf->ops->release(pipe, buf);
 	}
 out:
-	kfree(bufs);
+	kvfree(bufs);
 	return ret;
 }