]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/xprt.c
mmc: remove unused 'mode' from the mmc_host structure
[linux-2.6-omap-h63xx.git] / net / sunrpc / xprt.c
index c8c2edccad7e0dc2db35c754c9b56890a7c73965..cd641c8634f044c6bb580c2d725bdb908e97849d 100644 (file)
@@ -62,6 +62,9 @@ static inline void    do_xprt_reserve(struct rpc_task *);
 static void    xprt_connect_status(struct rpc_task *task);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
+static DEFINE_SPINLOCK(xprt_list_lock);
+static LIST_HEAD(xprt_list);
+
 /*
  * The transport code maintains an estimate on the maximum number of out-
  * 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)
 
+/**
+ * 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->ident == transport->ident)
+                       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
  * @task: task that is requesting access to the transport
@@ -118,6 +193,7 @@ out_sleep:
                rpc_sleep_on(&xprt->sending, task, NULL, NULL);
        return 0;
 }
+EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
 
 static void xprt_clear_locked(struct rpc_xprt *xprt)
 {
@@ -167,6 +243,7 @@ out_sleep:
                rpc_sleep_on(&xprt->sending, task, NULL, NULL);
        return 0;
 }
+EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
 
 static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
@@ -246,6 +323,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
                __xprt_lock_write_next(xprt);
        }
 }
+EXPORT_SYMBOL_GPL(xprt_release_xprt);
 
 /**
  * xprt_release_xprt_cong - allow other requests to use a transport
@@ -262,6 +340,7 @@ void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
                __xprt_lock_write_next_cong(xprt);
        }
 }
+EXPORT_SYMBOL_GPL(xprt_release_xprt_cong);
 
 static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
@@ -314,6 +393,7 @@ void xprt_release_rqst_cong(struct rpc_task *task)
 {
        __xprt_put_cong(task->tk_xprt, task->tk_rqstp);
 }
+EXPORT_SYMBOL_GPL(xprt_release_rqst_cong);
 
 /**
  * xprt_adjust_cwnd - adjust transport congestion window
@@ -345,6 +425,7 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result)
        xprt->cwnd = cwnd;
        __xprt_put_cong(xprt, req);
 }
+EXPORT_SYMBOL_GPL(xprt_adjust_cwnd);
 
 /**
  * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
@@ -359,6 +440,7 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
        else
                rpc_wake_up(&xprt->pending);
 }
+EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
 
 /**
  * xprt_wait_for_buffer_space - wait for transport output buffer to clear
@@ -373,6 +455,7 @@ void xprt_wait_for_buffer_space(struct rpc_task *task)
        task->tk_timeout = req->rq_timeout;
        rpc_sleep_on(&xprt->pending, task, NULL, NULL);
 }
+EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
 
 /**
  * xprt_write_space - wake the task waiting for transport output buffer space
@@ -393,6 +476,7 @@ void xprt_write_space(struct rpc_xprt *xprt)
        }
        spin_unlock_bh(&xprt->transport_lock);
 }
+EXPORT_SYMBOL_GPL(xprt_write_space);
 
 /**
  * xprt_set_retrans_timeout_def - set a request's retransmit timeout
@@ -406,6 +490,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task)
 {
        task->tk_timeout = task->tk_rqstp->rq_timeout;
 }
+EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def);
 
 /*
  * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
@@ -425,6 +510,7 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
        if (task->tk_timeout > max_timeout || task->tk_timeout == 0)
                task->tk_timeout = max_timeout;
 }
+EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt);
 
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
@@ -500,6 +586,7 @@ void xprt_disconnect(struct rpc_xprt *xprt)
        xprt_wake_pending_tasks(xprt, -ENOTCONN);
        spin_unlock_bh(&xprt->transport_lock);
 }
+EXPORT_SYMBOL_GPL(xprt_disconnect);
 
 static void
 xprt_init_autodisconnect(unsigned long data)
@@ -610,6 +697,7 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
        xprt->stat.bad_xids++;
        return NULL;
 }
+EXPORT_SYMBOL_GPL(xprt_lookup_rqst);
 
 /**
  * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
@@ -629,6 +717,7 @@ void xprt_update_rtt(struct rpc_task *task)
                rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
        }
 }
+EXPORT_SYMBOL_GPL(xprt_update_rtt);
 
 /**
  * xprt_complete_rqst - called when reply processing is complete
@@ -653,6 +742,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
        req->rq_received = req->rq_private_buf.len = copied;
        rpc_wake_up_task(task);
 }
+EXPORT_SYMBOL_GPL(xprt_complete_rqst);
 
 static void xprt_timer(struct rpc_task *task)
 {
@@ -889,23 +979,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
  * @args: rpc transport creation arguments
  *
  */
-struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args)
+struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
 {
        struct rpc_xprt *xprt;
        struct rpc_rqst *req;
+       struct xprt_class *t;
 
-       switch (args->proto) {
-       case IPPROTO_UDP:
-               xprt = xs_setup_udp(args);
-               break;
-       case IPPROTO_TCP:
-               xprt = xs_setup_tcp(args);
-               break;
-       default:
-               printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
-                               args->proto);
-               return ERR_PTR(-EIO);
+       spin_lock(&xprt_list_lock);
+       list_for_each_entry(t, &xprt_list, list) {
+               if (t->ident == args->ident) {
+                       spin_unlock(&xprt_list_lock);
+                       goto found;
+               }
        }
+       spin_unlock(&xprt_list_lock);
+       printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident);
+       return ERR_PTR(-EIO);
+
+found:
+       xprt = t->setup(args);
        if (IS_ERR(xprt)) {
                dprintk("RPC:       xprt_create_transport: failed, %ld\n",
                                -PTR_ERR(xprt));