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
238 /*238 /*
239 * Send stuff239 * Send stuff
240 */240 */
241 atomic_long_t queuelen;
241 spinlock_t transport_lock; /* lock transport info */242 spinlock_t transport_lock; /* lock transport info */
242 spinlock_t reserve_lock; /* lock slot table */243 spinlock_t reserve_lock; /* lock slot table */
243 spinlock_t queue_lock; /* send/receive queue lock */244 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
15 struct kref xps_kref;15 struct kref xps_kref;
16 16
17 unsigned int xps_nxprts;17 unsigned int xps_nxprts;
18 unsigned int xps_nactive;
19 atomic_long_t xps_queuelen;
18 struct list_head xps_xprt_list;20 struct list_head xps_xprt_list;
19 21
20 struct net * xps_net;22 struct net * xps_net;
net/sunrpc/clnt.c+37−3
@@ -968,13 +968,47 @@ out: · 967 unmodified lines
968}968}
969EXPORT_SYMBOL_GPL(rpc_bind_new_program);969EXPORT_SYMBOL_GPL(rpc_bind_new_program);
970 970
971static struct rpc_xprt *
972rpc_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
988static void
989rpc_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
971void rpc_task_release_transport(struct rpc_task *task)1002void rpc_task_release_transport(struct rpc_task *task)
972{1003{
973 struct rpc_xprt *xprt = task->tk_xprt;1004 struct rpc_xprt *xprt = task->tk_xprt;
974 1005
975 if (xprt) {1006 if (xprt) {
976 task->tk_xprt = NULL;1007 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);
978 }1012 }
979}1013}
980EXPORT_SYMBOL_GPL(rpc_task_release_transport);1014EXPORT_SYMBOL_GPL(rpc_task_release_transport);
@@ -983,6 +1017,7 @@ void rpc_task_release_client(struct rpc_task *task) · 2 unmodified lines
983{1017{
984 struct rpc_clnt *clnt = task->tk_client;1018 struct rpc_clnt *clnt = task->tk_client;
985 1019
1020 rpc_task_release_transport(task);
986 if (clnt != NULL) {1021 if (clnt != NULL) {
987 /* Remove from client task list */1022 /* Remove from client task list */
988 spin_lock(&clnt->cl_lock);1023 spin_lock(&clnt->cl_lock);
@@ -992,14 +1027,13 @@ void rpc_task_release_client(struct rpc_task *task) · 3 unmodified lines
992 1027
993 rpc_release_client(clnt);1028 rpc_release_client(clnt);
994 }1029 }
995 rpc_task_release_transport(task);
996}1030}
997 1031
998static1032static
999void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)1033void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
1000{1034{
1001 if (!task->tk_xprt)1035 if (!task->tk_xprt)
1002 task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);1036 task->tk_xprt = rpc_task_get_xprt(clnt);
1003}1037}
1004 1038
1005static1039static
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
36 if (xps->xps_nxprts == 0)36 if (xps->xps_nxprts == 0)
37 xps->xps_net = xprt->xprt_net;37 xps->xps_net = xprt->xprt_net;
38 xps->xps_nxprts++;38 xps->xps_nxprts++;
39 xps->xps_nactive++;
39}40}
40 41
41/**42/**
@@ -62,6 +63,7 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, · 20 unmodified lines
62{63{
63 if (unlikely(xprt == NULL))64 if (unlikely(xprt == NULL))
64 return;65 return;
66 xps->xps_nactive--;
65 xps->xps_nxprts--;67 xps->xps_nxprts--;
66 if (xps->xps_nxprts == 0)68 if (xps->xps_nxprts == 0)
67 xps->xps_net = NULL;69 xps->xps_net = NULL;
@@ -317,8 +319,24 @@ struct rpc_xprt *xprt_switch_find_next_entry_roundrobin(struct list_head *head, · 249 unmodified lines
317static319static
318struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)320struct rpc_xprt *xprt_iter_next_entry_roundrobin(struct rpc_xprt_iter *xpi)
319{321{
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,
321 xprt_switch_find_next_entry_roundrobin);330 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;
322}340}
323 341
324static342static

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