[Devel] [PATCH rh7 6/7] pipe: uncharge page on ->steal

Vladimir Davydov vdavydov at virtuozzo.com
Mon May 30 07:23:22 PDT 2016


A stolen pipe page may be reused for mapping to userspace, which
requires clean mapcount. So we must uncharge the page and reset its
mapcount on ->steal.

Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
 fs/pipe.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 975fe3fe11a8..03f1778476c4 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -22,6 +22,7 @@
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
 #include <linux/aio.h>
+#include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -229,6 +230,18 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
 		page_cache_release(page);
 }
 
+static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
+			       struct pipe_buffer *buf)
+{
+	struct page *page = buf->page;
+
+	if (page_count(page) == 1) {
+		memcg_kmem_uncharge_pages(page, 0);
+		lock_page(page);
+		return 0;
+	}
+	return 1;
+}
 /**
  * generic_pipe_buf_map - virtually map a pipe buffer
  * @pipe:	the pipe that the buffer belongs to
@@ -359,7 +372,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
 	.unmap = generic_pipe_buf_unmap,
 	.confirm = generic_pipe_buf_confirm,
 	.release = anon_pipe_buf_release,
-	.steal = generic_pipe_buf_steal,
+	.steal = anon_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
 };
 
@@ -369,7 +382,7 @@ static const struct pipe_buf_operations packet_pipe_buf_ops = {
 	.unmap = generic_pipe_buf_unmap,
 	.confirm = generic_pipe_buf_confirm,
 	.release = anon_pipe_buf_release,
-	.steal = generic_pipe_buf_steal,
+	.steal = anon_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
 };
 
-- 
2.1.4



More information about the Devel mailing list