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: Andy Grover <andy.grover@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Andy Grover 2009-08-21 12:28:34 +00:00 committed by David S. Miller
parent 40d866095d
commit 335776bd69
5 changed files with 28 additions and 10 deletions

View file

@ -282,6 +282,7 @@ struct rds_transport rds_ib_transport = {
.flush_mrs = rds_ib_flush_mrs,
.t_owner = THIS_MODULE,
.t_name = "infiniband",
.t_type = RDS_TRANS_IB
};
int __init rds_ib_init(void)

View file

@ -284,6 +284,7 @@ struct rds_transport rds_iw_transport = {
.flush_mrs = rds_iw_flush_mrs,
.t_owner = THIS_MODULE,
.t_name = "iwarp",
.t_type = RDS_TRANS_IWARP,
.t_prefer_loopback = 1,
};

View file

@ -311,11 +311,17 @@ struct rds_notifier {
* 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 {
char t_name[TRANSNAMSIZ];
struct list_head t_item;
struct module *t_owner;
unsigned int t_prefer_loopback:1;
unsigned int t_type;
int (*laddr_check)(__be32 addr);
int (*conn_alloc)(struct rds_connection *conn, gfp_t gfp);

View file

@ -271,6 +271,7 @@ struct rds_transport rds_tcp_transport = {
.exit = rds_tcp_exit,
.t_owner = THIS_MODULE,
.t_name = "tcp",
.t_type = RDS_TRANS_TCP,
.t_prefer_loopback = 1,
};

View file

@ -37,7 +37,7 @@
#include "rds.h"
#include "loop.h"
static LIST_HEAD(rds_transports);
static struct rds_transport *transports[RDS_TRANS_COUNT];
static DECLARE_RWSEM(rds_trans_sem);
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);
list_add_tail(&trans->t_item, &rds_transports);
printk(KERN_INFO "Registered RDS/%s transport\n", trans->t_name);
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);
}
up_write(&rds_trans_sem);
@ -59,7 +64,7 @@ void rds_trans_unregister(struct rds_transport *trans)
{
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);
up_write(&rds_trans_sem);
@ -68,16 +73,17 @@ EXPORT_SYMBOL_GPL(rds_trans_unregister);
struct rds_transport *rds_trans_get_preferred(__be32 addr)
{
struct rds_transport *trans;
struct rds_transport *ret = NULL;
int i;
if (IN_LOOPBACK(ntohl(addr)))
return &rds_loop_transport;
down_read(&rds_trans_sem);
list_for_each_entry(trans, &rds_transports, t_item) {
if (trans->laddr_check(addr) == 0) {
ret = trans;
for (i = 0; i < RDS_TRANS_COUNT; i++)
{
if (transports[i] && (transports[i]->laddr_check(addr) == 0)) {
ret = transports[i];
break;
}
}
@ -99,12 +105,15 @@ unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
struct rds_transport *trans;
unsigned int total = 0;
unsigned int part;
int i;
rds_info_iter_unmap(iter);
down_read(&rds_trans_sem);
list_for_each_entry(trans, &rds_transports, t_item) {
if (trans->stats_info_copy == NULL)
for (i = 0; i < RDS_TRANS_COUNT; i++)
{
trans = transports[i];
if (!trans || !trans->stats_info_copy)
continue;
part = trans->stats_info_copy(iter, avail);