SUNRPC: Provide a new API for registering transport implementations
To allow transport capabilities to be loaded dynamically, provide an API for registering and unregistering the transports with the RPC client. Eventually xprt_create_transport() will be changed to search the list of registered transports when initializing a fresh transport. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Tom Talpey <tmt@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
1244480976
commit
81c098af3d
2 changed files with 86 additions and 0 deletions
|
@ -208,6 +208,15 @@ struct rpc_xprtsock_create {
|
||||||
struct rpc_timeout * timeout; /* optional timeout parameters */
|
struct rpc_timeout * timeout; /* optional timeout parameters */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xprt_class {
|
||||||
|
struct list_head list;
|
||||||
|
unsigned short family;
|
||||||
|
int protocol;
|
||||||
|
struct rpc_xprt * (*setup)(struct rpc_xprtsock_create *);
|
||||||
|
struct module *owner;
|
||||||
|
char name[32];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transport operations used by ULPs
|
* Transport operations used by ULPs
|
||||||
*/
|
*/
|
||||||
|
@ -239,6 +248,8 @@ static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *
|
||||||
/*
|
/*
|
||||||
* Transport switch helper functions
|
* Transport switch helper functions
|
||||||
*/
|
*/
|
||||||
|
int xprt_register_transport(struct xprt_class *type);
|
||||||
|
int xprt_unregister_transport(struct xprt_class *type);
|
||||||
void xprt_set_retrans_timeout_def(struct rpc_task *task);
|
void xprt_set_retrans_timeout_def(struct rpc_task *task);
|
||||||
void xprt_set_retrans_timeout_rtt(struct rpc_task *task);
|
void xprt_set_retrans_timeout_rtt(struct rpc_task *task);
|
||||||
void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
|
void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
|
||||||
|
|
|
@ -62,6 +62,9 @@ static inline void do_xprt_reserve(struct rpc_task *);
|
||||||
static void xprt_connect_status(struct rpc_task *task);
|
static void xprt_connect_status(struct rpc_task *task);
|
||||||
static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
|
static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
|
||||||
|
|
||||||
|
static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
static LIST_HEAD(xprt_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The transport code maintains an estimate on the maximum number of out-
|
* The transport code maintains an estimate on the maximum number of out-
|
||||||
* standing RPC requests, using a smoothed version of the congestion
|
* standing RPC requests, using a smoothed version of the congestion
|
||||||
|
@ -80,6 +83,78 @@ static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
|
||||||
|
|
||||||
#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
|
#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xprt_register_transport - register a transport implementation
|
||||||
|
* @transport: transport to register
|
||||||
|
*
|
||||||
|
* If a transport implementation is loaded as a kernel module, it can
|
||||||
|
* call this interface to make itself known to the RPC client.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0: transport successfully registered
|
||||||
|
* -EEXIST: transport already registered
|
||||||
|
* -EINVAL: transport module being unloaded
|
||||||
|
*/
|
||||||
|
int xprt_register_transport(struct xprt_class *transport)
|
||||||
|
{
|
||||||
|
struct xprt_class *t;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = -EEXIST;
|
||||||
|
spin_lock(&xprt_list_lock);
|
||||||
|
list_for_each_entry(t, &xprt_list, list) {
|
||||||
|
/* don't register the same transport class twice */
|
||||||
|
if (t == transport)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = -EINVAL;
|
||||||
|
if (try_module_get(THIS_MODULE)) {
|
||||||
|
list_add_tail(&transport->list, &xprt_list);
|
||||||
|
printk(KERN_INFO "RPC: Registered %s transport module.\n",
|
||||||
|
transport->name);
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock(&xprt_list_lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xprt_register_transport);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xprt_unregister_transport - unregister a transport implementation
|
||||||
|
* transport: transport to unregister
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0: transport successfully unregistered
|
||||||
|
* -ENOENT: transport never registered
|
||||||
|
*/
|
||||||
|
int xprt_unregister_transport(struct xprt_class *transport)
|
||||||
|
{
|
||||||
|
struct xprt_class *t;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
spin_lock(&xprt_list_lock);
|
||||||
|
list_for_each_entry(t, &xprt_list, list) {
|
||||||
|
if (t == transport) {
|
||||||
|
printk(KERN_INFO
|
||||||
|
"RPC: Unregistered %s transport module.\n",
|
||||||
|
transport->name);
|
||||||
|
list_del_init(&transport->list);
|
||||||
|
module_put(THIS_MODULE);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = -ENOENT;
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock(&xprt_list_lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xprt_unregister_transport);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xprt_reserve_xprt - serialize write access to transports
|
* xprt_reserve_xprt - serialize write access to transports
|
||||||
* @task: task that is requesting access to the transport
|
* @task: task that is requesting access to the transport
|
||||||
|
|
Loading…
Add table
Reference in a new issue