diff options
Diffstat (limited to 'fs/select.c')
-rw-r--r-- | fs/select.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/fs/select.c b/fs/select.c index 6b14dc7df3a4..f9f49c40cfd4 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/hrtimer.h> | 28 | #include <linux/hrtimer.h> |
29 | #include <linux/sched/rt.h> | 29 | #include <linux/sched/rt.h> |
30 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
31 | #include <net/ll_poll.h> | ||
31 | 32 | ||
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | 34 | ||
@@ -386,9 +387,10 @@ get_max: | |||
386 | #define POLLEX_SET (POLLPRI) | 387 | #define POLLEX_SET (POLLPRI) |
387 | 388 | ||
388 | static inline void wait_key_set(poll_table *wait, unsigned long in, | 389 | static inline void wait_key_set(poll_table *wait, unsigned long in, |
389 | unsigned long out, unsigned long bit) | 390 | unsigned long out, unsigned long bit, |
391 | unsigned int ll_flag) | ||
390 | { | 392 | { |
391 | wait->_key = POLLEX_SET; | 393 | wait->_key = POLLEX_SET | ll_flag; |
392 | if (in & bit) | 394 | if (in & bit) |
393 | wait->_key |= POLLIN_SET; | 395 | wait->_key |= POLLIN_SET; |
394 | if (out & bit) | 396 | if (out & bit) |
@@ -402,6 +404,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
402 | poll_table *wait; | 404 | poll_table *wait; |
403 | int retval, i, timed_out = 0; | 405 | int retval, i, timed_out = 0; |
404 | unsigned long slack = 0; | 406 | unsigned long slack = 0; |
407 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; | ||
408 | unsigned long busy_end = 0; | ||
405 | 409 | ||
406 | rcu_read_lock(); | 410 | rcu_read_lock(); |
407 | retval = max_select_fd(n, fds); | 411 | retval = max_select_fd(n, fds); |
@@ -424,6 +428,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
424 | retval = 0; | 428 | retval = 0; |
425 | for (;;) { | 429 | for (;;) { |
426 | unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; | 430 | unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; |
431 | bool can_busy_loop = false; | ||
427 | 432 | ||
428 | inp = fds->in; outp = fds->out; exp = fds->ex; | 433 | inp = fds->in; outp = fds->out; exp = fds->ex; |
429 | rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; | 434 | rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; |
@@ -451,7 +456,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
451 | f_op = f.file->f_op; | 456 | f_op = f.file->f_op; |
452 | mask = DEFAULT_POLLMASK; | 457 | mask = DEFAULT_POLLMASK; |
453 | if (f_op && f_op->poll) { | 458 | if (f_op && f_op->poll) { |
454 | wait_key_set(wait, in, out, bit); | 459 | wait_key_set(wait, in, out, |
460 | bit, busy_flag); | ||
455 | mask = (*f_op->poll)(f.file, wait); | 461 | mask = (*f_op->poll)(f.file, wait); |
456 | } | 462 | } |
457 | fdput(f); | 463 | fdput(f); |
@@ -470,6 +476,18 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
470 | retval++; | 476 | retval++; |
471 | wait->_qproc = NULL; | 477 | wait->_qproc = NULL; |
472 | } | 478 | } |
479 | /* got something, stop busy polling */ | ||
480 | if (retval) { | ||
481 | can_busy_loop = false; | ||
482 | busy_flag = 0; | ||
483 | |||
484 | /* | ||
485 | * only remember a returned | ||
486 | * POLL_BUSY_LOOP if we asked for it | ||
487 | */ | ||
488 | } else if (busy_flag & mask) | ||
489 | can_busy_loop = true; | ||
490 | |||
473 | } | 491 | } |
474 | } | 492 | } |
475 | if (res_in) | 493 | if (res_in) |
@@ -488,6 +506,17 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
488 | break; | 506 | break; |
489 | } | 507 | } |
490 | 508 | ||
509 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ | ||
510 | if (can_busy_loop && !need_resched()) { | ||
511 | if (!busy_end) { | ||
512 | busy_end = busy_loop_end_time(); | ||
513 | continue; | ||
514 | } | ||
515 | if (!busy_loop_timeout(busy_end)) | ||
516 | continue; | ||
517 | } | ||
518 | busy_flag = 0; | ||
519 | |||
491 | /* | 520 | /* |
492 | * If this is the first loop and we have a timeout | 521 | * If this is the first loop and we have a timeout |
493 | * given, then we convert to ktime_t and set the to | 522 | * given, then we convert to ktime_t and set the to |
@@ -719,7 +748,9 @@ struct poll_list { | |||
719 | * pwait poll_table will be used by the fd-provided poll handler for waiting, | 748 | * pwait poll_table will be used by the fd-provided poll handler for waiting, |
720 | * if pwait->_qproc is non-NULL. | 749 | * if pwait->_qproc is non-NULL. |
721 | */ | 750 | */ |
722 | static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | 751 | static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait, |
752 | bool *can_busy_poll, | ||
753 | unsigned int busy_flag) | ||
723 | { | 754 | { |
724 | unsigned int mask; | 755 | unsigned int mask; |
725 | int fd; | 756 | int fd; |
@@ -733,7 +764,10 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | |||
733 | mask = DEFAULT_POLLMASK; | 764 | mask = DEFAULT_POLLMASK; |
734 | if (f.file->f_op && f.file->f_op->poll) { | 765 | if (f.file->f_op && f.file->f_op->poll) { |
735 | pwait->_key = pollfd->events|POLLERR|POLLHUP; | 766 | pwait->_key = pollfd->events|POLLERR|POLLHUP; |
767 | pwait->_key |= busy_flag; | ||
736 | mask = f.file->f_op->poll(f.file, pwait); | 768 | mask = f.file->f_op->poll(f.file, pwait); |
769 | if (mask & busy_flag) | ||
770 | *can_busy_poll = true; | ||
737 | } | 771 | } |
738 | /* Mask out unneeded events. */ | 772 | /* Mask out unneeded events. */ |
739 | mask &= pollfd->events | POLLERR | POLLHUP; | 773 | mask &= pollfd->events | POLLERR | POLLHUP; |
@@ -752,6 +786,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
752 | ktime_t expire, *to = NULL; | 786 | ktime_t expire, *to = NULL; |
753 | int timed_out = 0, count = 0; | 787 | int timed_out = 0, count = 0; |
754 | unsigned long slack = 0; | 788 | unsigned long slack = 0; |
789 | unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; | ||
790 | unsigned long busy_end = 0; | ||
755 | 791 | ||
756 | /* Optimise the no-wait case */ | 792 | /* Optimise the no-wait case */ |
757 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { | 793 | if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { |
@@ -764,6 +800,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
764 | 800 | ||
765 | for (;;) { | 801 | for (;;) { |
766 | struct poll_list *walk; | 802 | struct poll_list *walk; |
803 | bool can_busy_loop = false; | ||
767 | 804 | ||
768 | for (walk = list; walk != NULL; walk = walk->next) { | 805 | for (walk = list; walk != NULL; walk = walk->next) { |
769 | struct pollfd * pfd, * pfd_end; | 806 | struct pollfd * pfd, * pfd_end; |
@@ -778,9 +815,13 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
778 | * this. They'll get immediately deregistered | 815 | * this. They'll get immediately deregistered |
779 | * when we break out and return. | 816 | * when we break out and return. |
780 | */ | 817 | */ |
781 | if (do_pollfd(pfd, pt)) { | 818 | if (do_pollfd(pfd, pt, &can_busy_loop, |
819 | busy_flag)) { | ||
782 | count++; | 820 | count++; |
783 | pt->_qproc = NULL; | 821 | pt->_qproc = NULL; |
822 | /* found something, stop busy polling */ | ||
823 | busy_flag = 0; | ||
824 | can_busy_loop = false; | ||
784 | } | 825 | } |
785 | } | 826 | } |
786 | } | 827 | } |
@@ -797,6 +838,17 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
797 | if (count || timed_out) | 838 | if (count || timed_out) |
798 | break; | 839 | break; |
799 | 840 | ||
841 | /* only if found POLL_BUSY_LOOP sockets && not out of time */ | ||
842 | if (can_busy_loop && !need_resched()) { | ||
843 | if (!busy_end) { | ||
844 | busy_end = busy_loop_end_time(); | ||
845 | continue; | ||
846 | } | ||
847 | if (!busy_loop_timeout(busy_end)) | ||
848 | continue; | ||
849 | } | ||
850 | busy_flag = 0; | ||
851 | |||
800 | /* | 852 | /* |
801 | * If this is the first loop and we have a timeout | 853 | * If this is the first loop and we have a timeout |
802 | * given, then we convert to ktime_t and set the to | 854 | * given, then we convert to ktime_t and set the to |