bna: remove global bnad_list_mutex
[cascardo/linux.git] / fs / pipe.c
index 0d3f516..4b32928 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -21,6 +21,7 @@
 #include <linux/audit.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
+#include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -137,6 +138,22 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
                put_page(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) {
+               if (memcg_kmem_enabled()) {
+                       memcg_kmem_uncharge(page, 0);
+                       __ClearPageKmemcg(page);
+               }
+               __SetPageLocked(page);
+               return 0;
+       }
+       return 1;
+}
+
 /**
  * generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer
  * @pipe:      the pipe that the buffer belongs to
@@ -219,7 +236,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
        .can_merge = 1,
        .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,
 };
 
@@ -227,7 +244,7 @@ static const struct pipe_buf_operations packet_pipe_buf_ops = {
        .can_merge = 0,
        .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,
 };
 
@@ -405,7 +422,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                        int copied;
 
                        if (!page) {
-                               page = alloc_page(GFP_HIGHUSER);
+                               page = alloc_page(GFP_HIGHUSER | __GFP_ACCOUNT);
                                if (unlikely(!page)) {
                                        ret = ret ? : -ENOMEM;
                                        break;
@@ -611,7 +628,7 @@ struct pipe_inode_info *alloc_pipe_info(void)
 {
        struct pipe_inode_info *pipe;
 
-       pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+       pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
        if (pipe) {
                unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
                struct user_struct *user = get_current_user();
@@ -619,7 +636,9 @@ struct pipe_inode_info *alloc_pipe_info(void)
                if (!too_many_pipe_buffers_hard(user)) {
                        if (too_many_pipe_buffers_soft(user))
                                pipe_bufs = 1;
-                       pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+                       pipe->bufs = kcalloc(pipe_bufs,
+                                            sizeof(struct pipe_buffer),
+                                            GFP_KERNEL_ACCOUNT);
                }
 
                if (pipe->bufs) {
@@ -1010,7 +1029,8 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
        if (nr_pages < pipe->nrbufs)
                return -EBUSY;
 
-       bufs = kcalloc(nr_pages, sizeof(*bufs), GFP_KERNEL | __GFP_NOWARN);
+       bufs = kcalloc(nr_pages, sizeof(*bufs),
+                      GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
        if (unlikely(!bufs))
                return -ENOMEM;