aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-04-15 16:38:14 -0400
committerAndy Grover <andy.grover@oracle.com>2010-09-08 21:12:24 -0400
commit9e29db0e3645cafa980e68a9c717a761448389e1 (patch)
tree4ce87432acbda8e16c27c97f3d1ae5339bb53559 /net
parentacfcd4d4ec4ed8cb504f96d4fabb7a94029b362b (diff)
RDS: Use a generation counter to avoid rds_send_xmit loop
rds_send_xmit is required to loop around after it releases the lock because someone else could done a trylock, found someone working on the list and backed off. But, once we drop our lock, it is possible that someone else does come in and make progress on the list. We should detect this and not loop around if another process is actually working on the list. This patch adds a generation counter that is bumped every time we get the lock and do some send work. If the retry notices someone else has bumped the generation counter, it does not need to loop around and continue working. Signed-off-by: Chris Mason <chris.mason@oracle.com> Signed-off-by: Andy Grover <andy.grover@oracle.com>
Diffstat (limited to 'net')
-rw-r--r--net/rds/connection.c1
-rw-r--r--net/rds/rds.h1
-rw-r--r--net/rds/send.c11
3 files changed, 9 insertions, 4 deletions
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 56aebe444ad3..7e4e9dfdbc0b 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -147,6 +147,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
147 conn->c_next_tx_seq = 1; 147 conn->c_next_tx_seq = 1;
148 148
149 spin_lock_init(&conn->c_send_lock); 149 spin_lock_init(&conn->c_send_lock);
150 atomic_set(&conn->c_send_generation, 1);
150 INIT_LIST_HEAD(&conn->c_send_queue); 151 INIT_LIST_HEAD(&conn->c_send_queue);
151 INIT_LIST_HEAD(&conn->c_retrans); 152 INIT_LIST_HEAD(&conn->c_retrans);
152 153
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 2f19d49fac9c..b57cb50c1f22 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -92,6 +92,7 @@ struct rds_connection {
92 struct rds_cong_map *c_fcong; 92 struct rds_cong_map *c_fcong;
93 93
94 spinlock_t c_send_lock; /* protect send ring */ 94 spinlock_t c_send_lock; /* protect send ring */
95 atomic_t c_send_generation;
95 struct rds_message *c_xmit_rm; 96 struct rds_message *c_xmit_rm;
96 unsigned long c_xmit_sg; 97 unsigned long c_xmit_sg;
97 unsigned int c_xmit_hdr_off; 98 unsigned int c_xmit_hdr_off;
diff --git a/net/rds/send.c b/net/rds/send.c
index de5693cdcefb..663fd60b40cf 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -112,6 +112,7 @@ int rds_send_xmit(struct rds_connection *conn)
112 unsigned int tmp; 112 unsigned int tmp;
113 struct scatterlist *sg; 113 struct scatterlist *sg;
114 int ret = 0; 114 int ret = 0;
115 int gen = 0;
115 LIST_HEAD(to_be_dropped); 116 LIST_HEAD(to_be_dropped);
116 117
117restart: 118restart:
@@ -134,6 +135,8 @@ restart:
134 if (conn->c_trans->xmit_prepare) 135 if (conn->c_trans->xmit_prepare)
135 conn->c_trans->xmit_prepare(conn); 136 conn->c_trans->xmit_prepare(conn);
136 137
138 gen = atomic_inc_return(&conn->c_send_generation);
139
137 /* 140 /*
138 * spin trying to push headers and data down the connection until 141 * spin trying to push headers and data down the connection until
139 * the connection doesn't make forward progress. 142 * the connection doesn't make forward progress.
@@ -359,13 +362,13 @@ restart:
359 if (ret == 0) { 362 if (ret == 0) {
360 /* A simple bit test would be way faster than taking the 363 /* A simple bit test would be way faster than taking the
361 * spin lock */ 364 * spin lock */
362 spin_lock_irqsave(&conn->c_lock, flags); 365 smp_mb();
363 if (!list_empty(&conn->c_send_queue)) { 366 if (!list_empty(&conn->c_send_queue)) {
364 rds_stats_inc(s_send_lock_queue_raced); 367 rds_stats_inc(s_send_lock_queue_raced);
365 spin_unlock_irqrestore(&conn->c_lock, flags); 368 if (gen == atomic_read(&conn->c_send_generation)) {
366 goto restart; 369 goto restart;
370 }
367 } 371 }
368 spin_unlock_irqrestore(&conn->c_lock, flags);
369 } 372 }
370out: 373out:
371 return ret; 374 return ret;