History

SUNRPC: Add basic load balancing to the transport switch

For now, just count the queue length. It is less accurate than counting number of bytes queued, but easier to implement.

Trond Myklebust committed 9 years ago

Commit 21f0ffa1 parent 44942b44 files · +59 −4Browse files

Unified · Split

4 files
  1. include/linux/sunrpc/xprt.h +1 −0
  2. include/linux/sunrpc/xprtmultipath.h +2 −0
  3. net/sunrpc/clnt.c +37 −3
  4. net/sunrpc/xprtmultipath.c +19 −1
include/linux/sunrpc/xprt.h+1−0
@@ -238,6 +238,7 @@ struct rpc_xprt { · 237 unmodified lines
238238 /*
239239 * Send stuff
240240 */
241+ atomic_long_t queuelen;
241242 spinlock_t transport_lock; /* lock transport info */
242243 spinlock_t reserve_lock; /* lock slot table */
243244 spinlock_t queue_lock; /* send/receive queue lock */
include/linux/sunrpc/xprtmultipath.h+2−0
@@ -15,6 +15,8 @@ struct rpc_xprt_switch { · 14 unmodified lines
1515 struct kref xps_kref;
1616
1717 unsigned int xps_nxprts;
18+ unsigned int xps_nactive;
19+ atomic_long_t xps_queuelen;
1820 struct list_head xps_xprt_list;
1921
2022 struct net * xps_net;
net/sunrpc/clnt.c+37−3
@@ -968,13 +968,47 @@ out: · 967 unmodified lines
968968 }
969969 EXPORT_SYMBOL_GPL(rpc_bind_new_program);
970970
971+static struct rpc_xprt *
972+rpc_task_get_xprt(struct rpc_clnt *clnt)
973+{
974+ struct rpc_xprt_switch *xps;
975+ struct rpc_xprt *xprt= xprt_iter_get_next(&clnt->cl_xpi);
976+
977+ if (!xprt)
978+ return NULL;
979+ rcu_read_lock();
980+ xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
981+ atomic_long_inc(&xps->xps_queuelen);
982+ rcu_read_unlock();
983+ atomic_long_inc(&xprt->queuelen);
984+
985+ return xprt;
986+}
987+
988+static void
989+rpc_task_release_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
990+{
991+ struct rpc_xprt_switch *xps;
992+
993+ atomic_long_dec(&xprt->queuelen);
994+ rcu_read_lock();
995+ xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
996+ atomic_long_dec(&xps->xps_queuelen);
997+ rcu_read_unlock();
998+
999+ xprt_put(xprt);
1000+}
1001+
9711002 void rpc_task_release_transport(struct rpc_task *task)
9721003 {
9731004 struct rpc_xprt *xprt = task->tk_xprt;
9741005
9751006 if (xprt) {
9761007 task->tk_xprt = NULL;
977− xprt_put(xprt);
1008+ if (task->tk_client)
1009+ rpc_task_release_xprt(task->tk_client, xprt);
1010+ else
1011+ xprt_put(xprt);
9781012 }
9791013 }
9801014 EXPORT_SYMBOL_GPL(rpc_task_release_transport);
@@ -983,6 +1017,7 @@ void rpc_task_release_client(struct rpc_task *task) · 2 unmodified lines
9831017 {
9841018 struct rpc_clnt *clnt = task->tk_client;
9851019
1020+ rpc_task_release_transport(task);
9861021 if (clnt != NULL) {
9871022 /* Remove from client task list */
9881023 spin_lock(&clnt->cl_lock);
@@ -992,14 +1027,13 @@ void rpc_task_release_client(struct rpc_task *task) · 3 unmodified lines
9921027
9931028 rpc_release_client(clnt);
9941029 }
995− rpc_task_release_transport(task);
9961030 }
9971031
9981032 static
9991033 void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
10001034 {
10011035 if (!task->tk_xprt)
1002− task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
1036+ task->tk_xprt = rpc_task_get_xprt(clnt);
10031037 }
10041038
10051039 static
net/sunrpc/xprtmultipath.c+19−1
@@ -36,6 +36,7 @@ static void xprt_switch_add_xprt_locked(struct rpc_xprt_switch *xps, · 35 unmodified lines
3636 if (xps->xps_nxprts == 0)
3737 xps->xps_net = xprt->xprt_net;
3838 xps->xps_nxprts++;
39+ xps->xps_nactive++;
3940 }
4041
4142 /**
@@ -62,6 +63,7 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, · 20 unmodified lines
6263 {
6364 if (unlikely(xprt == NULL))
6465 return;
66+ xps->xps_nactive--;
6567 xps->xps_nxprts--;
6668 if (xps->xps_nxprts == 0)
6769 xps->xps_net = NULL;
@@ -317,8 +319,24 @@ struct rpc_xprt *xprt_switch_find_next_entry_roundrobin(struct list_head *head, · 249 unmodified lines
317319 static
318320 struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)
319321 {
320− return xprt_iter_next_entry_multiple(xpi,
322+ struct rpc_xprt_switch *xps = rcu_dereference(xpi->xpi_xpswitch);
323+ struct rpc_xprt *xprt;
324+ unsigned long xprt_queuelen;
325+ unsigned long xps_queuelen;
326+ unsigned long xps_avglen;
327+
328+ do {
329+ xprt = xprt_iter_next_entry_multiple(xpi,
321330 xprt_switch_find_next_entry_roundrobin);
331+ if (xprt == NULL)
332+ break;
333+ xprt_queuelen = atomic_long_read(&xprt->queuelen);
334+ if (xprt_queuelen <= 2)
335+ break;
336+ xps_queuelen = atomic_long_read(&xps->xps_queuelen);
337+ xps_avglen = DIV_ROUND_UP(xps_queuelen, xps->xps_nactive);
338+ } while (xprt_queuelen > xps_avglen);
339+ return xprt;
322340 }
323341
324342 static

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t