Commit 335776bd authored by Andy Grover's avatar Andy Grover Committed by David S. Miller

RDS: Track transports via an array, not a list

Now that transports can be loaded in arbitrary order,
it is important for rds_trans_get_preferred() to look
for them in a particular order, instead of walking the list
until it finds a transport that works for a given address.
Now, each transport registers for a specific transport slot,
and these are ordered so that preferred transports come first,
and then if they are not loaded, other transports are queried.
Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 40d86609
...@@ -282,6 +282,7 @@ struct rds_transport rds_ib_transport = { ...@@ -282,6 +282,7 @@ struct rds_transport rds_ib_transport = {
.flush_mrs = rds_ib_flush_mrs, .flush_mrs = rds_ib_flush_mrs,
.t_owner = THIS_MODULE, .t_owner = THIS_MODULE,
.t_name = "infiniband", .t_name = "infiniband",
.t_type = RDS_TRANS_IB
}; };
int __init rds_ib_init(void) int __init rds_ib_init(void)
......
...@@ -284,6 +284,7 @@ struct rds_transport rds_iw_transport = { ...@@ -284,6 +284,7 @@ struct rds_transport rds_iw_transport = {
.flush_mrs = rds_iw_flush_mrs, .flush_mrs = rds_iw_flush_mrs,
.t_owner = THIS_MODULE, .t_owner = THIS_MODULE,
.t_name = "iwarp", .t_name = "iwarp",
.t_type = RDS_TRANS_IWARP,
.t_prefer_loopback = 1, .t_prefer_loopback = 1,
}; };
......
...@@ -311,11 +311,17 @@ struct rds_notifier { ...@@ -311,11 +311,17 @@ struct rds_notifier {
* flag and header. * flag and header.
*/ */
#define RDS_TRANS_IB 0
#define RDS_TRANS_IWARP 1
#define RDS_TRANS_TCP 2
#define RDS_TRANS_COUNT 3
struct rds_transport { struct rds_transport {
char t_name[TRANSNAMSIZ]; char t_name[TRANSNAMSIZ];
struct list_head t_item; struct list_head t_item;
struct module *t_owner; struct module *t_owner;
unsigned int t_prefer_loopback:1; unsigned int t_prefer_loopback:1;
unsigned int t_type;
int (*laddr_check)(__be32 addr); int (*laddr_check)(__be32 addr);
int (*conn_alloc)(struct rds_connection *conn, gfp_t gfp); int (*conn_alloc)(struct rds_connection *conn, gfp_t gfp);
......
...@@ -271,6 +271,7 @@ struct rds_transport rds_tcp_transport = { ...@@ -271,6 +271,7 @@ struct rds_transport rds_tcp_transport = {
.exit = rds_tcp_exit, .exit = rds_tcp_exit,
.t_owner = THIS_MODULE, .t_owner = THIS_MODULE,
.t_name = "tcp", .t_name = "tcp",
.t_type = RDS_TRANS_TCP,
.t_prefer_loopback = 1, .t_prefer_loopback = 1,
}; };
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "rds.h" #include "rds.h"
#include "loop.h" #include "loop.h"
static LIST_HEAD(rds_transports); static struct rds_transport *transports[RDS_TRANS_COUNT];
static DECLARE_RWSEM(rds_trans_sem); static DECLARE_RWSEM(rds_trans_sem);
int rds_trans_register(struct rds_transport *trans) int rds_trans_register(struct rds_transport *trans)
...@@ -46,8 +46,13 @@ int rds_trans_register(struct rds_transport *trans) ...@@ -46,8 +46,13 @@ int rds_trans_register(struct rds_transport *trans)
down_write(&rds_trans_sem); down_write(&rds_trans_sem);
list_add_tail(&trans->t_item, &rds_transports); if (transports[trans->t_type])
printk(KERN_ERR "RDS Transport type %d already registered\n",
trans->t_type);
else {
transports[trans->t_type] = trans;
printk(KERN_INFO "Registered RDS/%s transport\n", trans->t_name); printk(KERN_INFO "Registered RDS/%s transport\n", trans->t_name);
}
up_write(&rds_trans_sem); up_write(&rds_trans_sem);
...@@ -59,7 +64,7 @@ void rds_trans_unregister(struct rds_transport *trans) ...@@ -59,7 +64,7 @@ void rds_trans_unregister(struct rds_transport *trans)
{ {
down_write(&rds_trans_sem); down_write(&rds_trans_sem);
list_del_init(&trans->t_item); transports[trans->t_type] = NULL;
printk(KERN_INFO "Unregistered RDS/%s transport\n", trans->t_name); printk(KERN_INFO "Unregistered RDS/%s transport\n", trans->t_name);
up_write(&rds_trans_sem); up_write(&rds_trans_sem);
...@@ -68,16 +73,17 @@ EXPORT_SYMBOL_GPL(rds_trans_unregister); ...@@ -68,16 +73,17 @@ EXPORT_SYMBOL_GPL(rds_trans_unregister);
struct rds_transport *rds_trans_get_preferred(__be32 addr) struct rds_transport *rds_trans_get_preferred(__be32 addr)
{ {
struct rds_transport *trans;
struct rds_transport *ret = NULL; struct rds_transport *ret = NULL;
int i;
if (IN_LOOPBACK(ntohl(addr))) if (IN_LOOPBACK(ntohl(addr)))
return &rds_loop_transport; return &rds_loop_transport;
down_read(&rds_trans_sem); down_read(&rds_trans_sem);
list_for_each_entry(trans, &rds_transports, t_item) { for (i = 0; i < RDS_TRANS_COUNT; i++)
if (trans->laddr_check(addr) == 0) { {
ret = trans; if (transports[i] && (transports[i]->laddr_check(addr) == 0)) {
ret = transports[i];
break; break;
} }
} }
...@@ -99,12 +105,15 @@ unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter, ...@@ -99,12 +105,15 @@ unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
struct rds_transport *trans; struct rds_transport *trans;
unsigned int total = 0; unsigned int total = 0;
unsigned int part; unsigned int part;
int i;
rds_info_iter_unmap(iter); rds_info_iter_unmap(iter);
down_read(&rds_trans_sem); down_read(&rds_trans_sem);
list_for_each_entry(trans, &rds_transports, t_item) { for (i = 0; i < RDS_TRANS_COUNT; i++)
if (trans->stats_info_copy == NULL) {
trans = transports[i];
if (!trans || !trans->stats_info_copy)
continue; continue;
part = trans->stats_info_copy(iter, avail); part = trans->stats_info_copy(iter, avail);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment