diff options
author | Michael Kerrisk (man-pages) <mtk.manpages@gmail.com> | 2016-10-11 16:53:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-11 18:06:32 -0400 |
commit | 9c87bcf0a31b338dc8a69a5d251a037565a94e13 (patch) | |
tree | 47c85164ba4bfcbd053dfa3cd68762337bec2a12 | |
parent | a005ca0e6813e1d796a7422a7e31d8b8d6555df1 (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.c | 36 |
1 files changed, 18 insertions, 18 deletions
@@ -601,22 +601,20 @@ pipe_fasync(int fd, struct file *filp, int on) | |||
601 | return retval; | 601 | return retval; |
602 | } | 602 | } |
603 | 603 | ||
604 | static void account_pipe_buffers(struct user_struct *user, | 604 | static 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 | ||
610 | static bool too_many_pipe_buffers_soft(struct user_struct *user) | 610 | static 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 | ||
616 | static bool too_many_pipe_buffers_hard(struct user_struct *user) | 615 | static 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 | ||
622 | struct pipe_inode_info *alloc_pipe_info(void) | 620 | struct 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 | ||
654 | out_revert_acct: | 653 | out_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); |
657 | out_free_uid: | 656 | out_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 | ||
1111 | out_revert_acct: | 1111 | out_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 | ||