aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Kerrisk (man-pages) <mtk.manpages@gmail.com>2016-10-11 16:53:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-11 18:06:32 -0400
commit9c87bcf0a31b338dc8a69a5d251a037565a94e13 (patch)
tree47c85164ba4bfcbd053dfa3cd68762337bec2a12
parenta005ca0e6813e1d796a7422a7e31d8b8d6555df1 (diff)
pipe: make account_pipe_buffers() return a value, and use it
This is an optional patch, to provide a small performance improvement. Alter account_pipe_buffers() so that it returns the new value in user->pipe_bufs. This means that we can refactor too_many_pipe_buffers_soft() and too_many_pipe_buffers_hard() to avoid the costs of repeated use of atomic_long_read() to get the value user->pipe_bufs. Link: http://lkml.kernel.org/r/93e5f193-1e5e-3e1f-3a20-eae79b7e1310@gmail.com Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com> Reviewed-by: Vegard Nossum <vegard.nossum@oracle.com> Cc: Willy Tarreau <w@1wt.eu> Cc: <socketpair@gmail.com> Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Jens Axboe <axboe@fb.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/pipe.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 83a292464de7..5ff02c4afe9f 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -601,22 +601,20 @@ pipe_fasync(int fd, struct file *filp, int on)
601 return retval; 601 return retval;
602} 602}
603 603
604static void account_pipe_buffers(struct user_struct *user, 604static unsigned long account_pipe_buffers(struct user_struct *user,
605 unsigned long old, unsigned long new) 605 unsigned long old, unsigned long new)
606{ 606{
607 atomic_long_add(new - old, &user->pipe_bufs); 607 return atomic_long_add_return(new - old, &user->pipe_bufs);
608} 608}
609 609
610static bool too_many_pipe_buffers_soft(struct user_struct *user) 610static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
611{ 611{
612 return pipe_user_pages_soft && 612 return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft;
613 atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
614} 613}
615 614
616static bool too_many_pipe_buffers_hard(struct user_struct *user) 615static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
617{ 616{
618 return pipe_user_pages_hard && 617 return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
619 atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
620} 618}
621 619
622struct pipe_inode_info *alloc_pipe_info(void) 620struct pipe_inode_info *alloc_pipe_info(void)
@@ -624,19 +622,20 @@ struct pipe_inode_info *alloc_pipe_info(void)
624 struct pipe_inode_info *pipe; 622 struct pipe_inode_info *pipe;
625 unsigned long pipe_bufs = PIPE_DEF_BUFFERS; 623 unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
626 struct user_struct *user = get_current_user(); 624 struct user_struct *user = get_current_user();
625 unsigned long user_bufs;
627 626
628 pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT); 627 pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
629 if (pipe == NULL) 628 if (pipe == NULL)
630 goto out_free_uid; 629 goto out_free_uid;
631 630
632 account_pipe_buffers(user, 0, pipe_bufs); 631 user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
633 632
634 if (too_many_pipe_buffers_soft(user)) { 633 if (too_many_pipe_buffers_soft(user_bufs)) {
635 account_pipe_buffers(user, pipe_bufs, 1); 634 user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
636 pipe_bufs = 1; 635 pipe_bufs = 1;
637 } 636 }
638 637
639 if (too_many_pipe_buffers_hard(user)) 638 if (too_many_pipe_buffers_hard(user_bufs))
640 goto out_revert_acct; 639 goto out_revert_acct;
641 640
642 pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), 641 pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
@@ -652,7 +651,7 @@ struct pipe_inode_info *alloc_pipe_info(void)
652 } 651 }
653 652
654out_revert_acct: 653out_revert_acct:
655 account_pipe_buffers(user, pipe_bufs, 0); 654 (void) account_pipe_buffers(user, pipe_bufs, 0);
656 kfree(pipe); 655 kfree(pipe);
657out_free_uid: 656out_free_uid:
658 free_uid(user); 657 free_uid(user);
@@ -663,7 +662,7 @@ void free_pipe_info(struct pipe_inode_info *pipe)
663{ 662{
664 int i; 663 int i;
665 664
666 account_pipe_buffers(pipe->user, pipe->buffers, 0); 665 (void) account_pipe_buffers(pipe->user, pipe->buffers, 0);
667 free_uid(pipe->user); 666 free_uid(pipe->user);
668 for (i = 0; i < pipe->buffers; i++) { 667 for (i = 0; i < pipe->buffers; i++) {
669 struct pipe_buffer *buf = pipe->bufs + i; 668 struct pipe_buffer *buf = pipe->bufs + i;
@@ -1034,6 +1033,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
1034{ 1033{
1035 struct pipe_buffer *bufs; 1034 struct pipe_buffer *bufs;
1036 unsigned int size, nr_pages; 1035 unsigned int size, nr_pages;
1036 unsigned long user_bufs;
1037 long ret = 0; 1037 long ret = 0;
1038 1038
1039 size = round_pipe_size(arg); 1039 size = round_pipe_size(arg);
@@ -1053,11 +1053,11 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
1053 size > pipe_max_size && !capable(CAP_SYS_RESOURCE)) 1053 size > pipe_max_size && !capable(CAP_SYS_RESOURCE))
1054 return -EPERM; 1054 return -EPERM;
1055 1055
1056 account_pipe_buffers(pipe->user, pipe->buffers, nr_pages); 1056 user_bufs = account_pipe_buffers(pipe->user, pipe->buffers, nr_pages);
1057 1057
1058 if (nr_pages > pipe->buffers && 1058 if (nr_pages > pipe->buffers &&
1059 (too_many_pipe_buffers_hard(pipe->user) || 1059 (too_many_pipe_buffers_hard(user_bufs) ||
1060 too_many_pipe_buffers_soft(pipe->user)) && 1060 too_many_pipe_buffers_soft(user_bufs)) &&
1061 !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { 1061 !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
1062 ret = -EPERM; 1062 ret = -EPERM;
1063 goto out_revert_acct; 1063 goto out_revert_acct;
@@ -1109,7 +1109,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
1109 return nr_pages * PAGE_SIZE; 1109 return nr_pages * PAGE_SIZE;
1110 1110
1111out_revert_acct: 1111out_revert_acct:
1112 account_pipe_buffers(pipe->user, nr_pages, pipe->buffers); 1112 (void) account_pipe_buffers(pipe->user, nr_pages, pipe->buffers);
1113 return ret; 1113 return ret;
1114} 1114}
1115 1115