[Devel] [PATCH rh7] fs/fuse/dev: improve ->splice() with fragmented memory

Andrey Ryabinin aryabinin at virtuozzo.com
Wed Nov 29 16:59:01 MSK 2017


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 at virtuozzo.com>
---
 fs/fuse/dev.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 3427eddcfb17..83c30e51dfca 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1353,7 +1353,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;
 
@@ -1410,7 +1410,7 @@ out:
 	for (; page_nr < cs.nr_segs; page_nr++)
 		page_cache_release(bufs[page_nr].page);
 
-	kfree(bufs);
+	kvfree(bufs);
 	return ret;
 }
 
@@ -1991,7 +1991,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;
 
@@ -2049,7 +2049,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;
 }
 
-- 
2.13.6



More information about the Devel mailing list