diff options
| author | \"Talpey, Thomas\ <Thomas.Talpey@netapp.com> | 2007-09-10 13:46:00 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-10-09 17:17:40 -0400 |
| commit | 81c098af3da7981902e9f8163aeccc2467c4ba6d (patch) | |
| tree | b98e3c8c9e519e34abf721410de70373cedb4a9f /net/sunrpc | |
| parent | 1244480976d357447aeddd3f44977586bfa0462b (diff) | |
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>
Diffstat (limited to 'net/sunrpc')
| -rw-r--r-- | net/sunrpc/xprt.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index bc13616e7f..520859622a 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -62,6 +62,9 @@ static inline void do_xprt_reserve(struct rpc_task *); | |||
| 62 | static void xprt_connect_status(struct rpc_task *task); | 62 | static void xprt_connect_status(struct rpc_task *task); |
| 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
| 64 | 64 | ||
| 65 | static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED; | ||
| 66 | static LIST_HEAD(xprt_list); | ||
| 67 | |||
| 65 | /* | 68 | /* |
| 66 | * The transport code maintains an estimate on the maximum number of out- | 69 | * The transport code maintains an estimate on the maximum number of out- |
| 67 | * standing RPC requests, using a smoothed version of the congestion | 70 | * standing RPC requests, using a smoothed version of the congestion |
| @@ -81,6 +84,78 @@ static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | |||
| 81 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) | 84 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) |
| 82 | 85 | ||
| 83 | /** | 86 | /** |
| 87 | * xprt_register_transport - register a transport implementation | ||
| 88 | * @transport: transport to register | ||
| 89 | * | ||
| 90 | * If a transport implementation is loaded as a kernel module, it can | ||
| 91 | * call this interface to make itself known to the RPC client. | ||
| 92 | * | ||
| 93 | * Returns: | ||
| 94 | * 0: transport successfully registered | ||
| 95 | * -EEXIST: transport already registered | ||
| 96 | * -EINVAL: transport module being unloaded | ||
| 97 | */ | ||
| 98 | int xprt_register_transport(struct xprt_class *transport) | ||
| 99 | { | ||
| 100 | struct xprt_class *t; | ||
| 101 | int result; | ||
| 102 | |||
| 103 | result = -EEXIST; | ||
| 104 | spin_lock(&xprt_list_lock); | ||
| 105 | list_for_each_entry(t, &xprt_list, list) { | ||
| 106 | /* don't register the same transport class twice */ | ||
| 107 | if (t == transport) | ||
| 108 | goto out; | ||
| 109 | } | ||
| 110 | |||
| 111 | result = -EINVAL; | ||
| 112 | if (try_module_get(THIS_MODULE)) { | ||
| 113 | list_add_tail(&transport->list, &xprt_list); | ||
| 114 | printk(KERN_INFO "RPC: Registered %s transport module.\n", | ||
| 115 | transport->name); | ||
| 116 | result = 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | out: | ||
| 120 | spin_unlock(&xprt_list_lock); | ||
| 121 | return result; | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(xprt_register_transport); | ||
| 124 | |||
| 125 | /** | ||
| 126 | * xprt_unregister_transport - unregister a transport implementation | ||
| 127 | * transport: transport to unregister | ||
| 128 | * | ||
| 129 | * Returns: | ||
| 130 | * 0: transport successfully unregistered | ||
| 131 | * -ENOENT: transport never registered | ||
| 132 | */ | ||
| 133 | int xprt_unregister_transport(struct xprt_class *transport) | ||
| 134 | { | ||
| 135 | struct xprt_class *t; | ||
| 136 | int result; | ||
| 137 | |||
| 138 | result = 0; | ||
| 139 | spin_lock(&xprt_list_lock); | ||
| 140 | list_for_each_entry(t, &xprt_list, list) { | ||
| 141 | if (t == transport) { | ||
| 142 | printk(KERN_INFO | ||
| 143 | "RPC: Unregistered %s transport module.\n", | ||
| 144 | transport->name); | ||
| 145 | list_del_init(&transport->list); | ||
| 146 | module_put(THIS_MODULE); | ||
| 147 | goto out; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | result = -ENOENT; | ||
| 151 | |||
| 152 | out: | ||
| 153 | spin_unlock(&xprt_list_lock); | ||
| 154 | return result; | ||
| 155 | } | ||
| 156 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); | ||
| 157 | |||
| 158 | /** | ||
| 84 | * xprt_reserve_xprt - serialize write access to transports | 159 | * xprt_reserve_xprt - serialize write access to transports |
| 85 | * @task: task that is requesting access to the transport | 160 | * @task: task that is requesting access to the transport |
| 86 | * | 161 | * |
