OSDN Git Service

RDS: limit the number of times we loop in rds_send_xmit
authorChris Mason <chris.mason@oracle.com>
Fri, 3 Feb 2012 16:07:54 +0000 (11:07 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 Aug 2019 19:04:24 +0000 (12:04 -0700)
This will kick the RDS worker thread if we have been looping
too long.

Original commit from 2012 updated to include a change by
Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
that triggers "must_wake" if "rds_ib_recv_refill_one" fails.

Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/rds/ib_recv.c

index 3cae88c..1a8a4a7 100644 (file)
@@ -385,6 +385,7 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp)
        unsigned int posted = 0;
        int ret = 0;
        bool can_wait = !!(gfp & __GFP_DIRECT_RECLAIM);
+       bool must_wake = false;
        u32 pos;
 
        /* the goal here is to just make sure that someone, somewhere
@@ -405,6 +406,7 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp)
                recv = &ic->i_recvs[pos];
                ret = rds_ib_recv_refill_one(conn, recv, gfp);
                if (ret) {
+                       must_wake = true;
                        break;
                }
 
@@ -423,6 +425,11 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp)
                }
 
                posted++;
+
+               if ((posted > 128 && need_resched()) || posted > 8192) {
+                       must_wake = true;
+                       break;
+               }
        }
 
        /* We're doing flow control - update the window. */
@@ -445,10 +452,13 @@ void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp)
         * if we should requeue.
         */
        if (rds_conn_up(conn) &&
-           ((can_wait && rds_ib_ring_low(&ic->i_recv_ring)) ||
+           (must_wake ||
+           (can_wait && rds_ib_ring_low(&ic->i_recv_ring)) ||
            rds_ib_ring_empty(&ic->i_recv_ring))) {
                queue_delayed_work(rds_wq, &conn->c_recv_w, 1);
        }
+       if (can_wait)
+               cond_resched();
 }
 
 /*