]> Pileus Git - ~andy/linux/blobdiff - fs/select.c
net: sock: fix TCP_SKB_MIN_TRUESIZE
[~andy/linux] / fs / select.c
index 8c1c96c27062a504bfc151f33d335fcd8f6779b5..f28a585927256717bf85ff7f3c105a41c776b08a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/rcupdate.h>
 #include <linux/hrtimer.h>
 #include <linux/sched/rt.h>
+#include <net/ll_poll.h>
 
 #include <asm/uaccess.h>
 
@@ -384,9 +385,10 @@ get_max:
 #define POLLEX_SET (POLLPRI)
 
 static inline void wait_key_set(poll_table *wait, unsigned long in,
-                               unsigned long out, unsigned long bit)
+                               unsigned long out, unsigned long bit,
+                               unsigned int ll_flag)
 {
-       wait->_key = POLLEX_SET;
+       wait->_key = POLLEX_SET | ll_flag;
        if (in & bit)
                wait->_key |= POLLIN_SET;
        if (out & bit)
@@ -400,6 +402,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
        poll_table *wait;
        int retval, i, timed_out = 0;
        unsigned long slack = 0;
+       unsigned int ll_flag = ll_get_flag();
+       u64 ll_start = ll_start_time(ll_flag);
+       u64 ll_time = ll_run_time();
 
        rcu_read_lock();
        retval = max_select_fd(n, fds);
@@ -422,6 +427,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
        retval = 0;
        for (;;) {
                unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+               bool can_ll = false;
 
                inp = fds->in; outp = fds->out; exp = fds->ex;
                rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
@@ -449,7 +455,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
                                        f_op = f.file->f_op;
                                        mask = DEFAULT_POLLMASK;
                                        if (f_op && f_op->poll) {
-                                               wait_key_set(wait, in, out, bit);
+                                               wait_key_set(wait, in, out,
+                                                            bit, ll_flag);
                                                mask = (*f_op->poll)(f.file, wait);
                                        }
                                        fdput(f);
@@ -468,6 +475,11 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
                                                retval++;
                                                wait->_qproc = NULL;
                                        }
+                                       if (mask & POLL_LL)
+                                               can_ll = true;
+                                       /* got something, stop busy polling */
+                                       if (retval)
+                                               ll_flag = 0;
                                }
                        }
                        if (res_in)
@@ -486,6 +498,10 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
                        break;
                }
 
+               /* only if on, have sockets with POLL_LL and not out of time */
+               if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time))
+                       continue;
+
                /*
                 * If this is the first loop and we have a timeout
                 * given, then we convert to ktime_t and set the to
@@ -717,7 +733,8 @@ struct poll_list {
  * pwait poll_table will be used by the fd-provided poll handler for waiting,
  * if pwait->_qproc is non-NULL.
  */
-static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
+static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait,
+                                    bool *can_ll, unsigned int ll_flag)
 {
        unsigned int mask;
        int fd;
@@ -731,7 +748,10 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
                        mask = DEFAULT_POLLMASK;
                        if (f.file->f_op && f.file->f_op->poll) {
                                pwait->_key = pollfd->events|POLLERR|POLLHUP;
+                               pwait->_key |= ll_flag;
                                mask = f.file->f_op->poll(f.file, pwait);
+                               if (mask & POLL_LL)
+                                       *can_ll = true;
                        }
                        /* Mask out unneeded events. */
                        mask &= pollfd->events | POLLERR | POLLHUP;
@@ -750,6 +770,9 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
        ktime_t expire, *to = NULL;
        int timed_out = 0, count = 0;
        unsigned long slack = 0;
+       unsigned int ll_flag = ll_get_flag();
+       u64 ll_start = ll_start_time(ll_flag);
+       u64 ll_time = ll_run_time();
 
        /* Optimise the no-wait case */
        if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
@@ -762,6 +785,7 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
 
        for (;;) {
                struct poll_list *walk;
+               bool can_ll = false;
 
                for (walk = list; walk != NULL; walk = walk->next) {
                        struct pollfd * pfd, * pfd_end;
@@ -776,9 +800,10 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
                                 * this. They'll get immediately deregistered
                                 * when we break out and return.
                                 */
-                               if (do_pollfd(pfd, pt)) {
+                               if (do_pollfd(pfd, pt, &can_ll, ll_flag)) {
                                        count++;
                                        pt->_qproc = NULL;
+                                       ll_flag = 0;
                                }
                        }
                }
@@ -795,6 +820,10 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
                if (count || timed_out)
                        break;
 
+               /* only if on, have sockets with POLL_LL and not out of time */
+               if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time))
+                       continue;
+
                /*
                 * If this is the first loop and we have a timeout
                 * given, then we convert to ktime_t and set the to