Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-drm-fsl-dcu.git] / net / sunrpc / xprt.c
index 17f56cfe24127b47f2aabd943b03f2e25f647537..e7c71a1ea3d46dbcee26f25a49bfeb93bda6bb57 100644 (file)
@@ -410,7 +410,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task)
 /*
  * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
  * @task: task whose timeout is to be set
- * 
+ *
  * Set a request's retransmit timeout using the RTT estimator.
  */
 void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
@@ -459,7 +459,6 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
                if (to->to_maxval && req->rq_timeout >= to->to_maxval)
                        req->rq_timeout = to->to_maxval;
                req->rq_retries++;
-               pprintk("RPC: %lu retrans\n", jiffies);
        } else {
                req->rq_timeout = to->to_initval;
                req->rq_retries = 0;
@@ -468,7 +467,6 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
                spin_lock_bh(&xprt->transport_lock);
                rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
                spin_unlock_bh(&xprt->transport_lock);
-               pprintk("RPC: %lu timeout\n", jiffies);
                status = -ETIMEDOUT;
        }
 
@@ -479,9 +477,10 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
        return status;
 }
 
-static void xprt_autoclose(void *args)
+static void xprt_autoclose(struct work_struct *work)
 {
-       struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+       struct rpc_xprt *xprt =
+               container_of(work, struct rpc_xprt, task_cleanup);
 
        xprt_disconnect(xprt);
        xprt->ops->close(xprt);
@@ -585,13 +584,6 @@ static void xprt_connect_status(struct rpc_task *task)
                                task->tk_pid, -task->tk_status, task->tk_client->cl_server);
                xprt_release_write(xprt, task);
                task->tk_status = -EIO;
-               return;
-       }
-
-       /* if soft mounted, just cause this RPC to fail */
-       if (RPC_IS_SOFT(task)) {
-               xprt_release_write(xprt, task);
-               task->tk_status = -EIO;
        }
 }
 
@@ -601,7 +593,7 @@ static void xprt_connect_status(struct rpc_task *task)
  * @xid: RPC XID of incoming reply
  *
  */
-struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
 {
        struct list_head *pos;
 
@@ -808,7 +800,7 @@ void xprt_reserve(struct rpc_task *task)
        spin_unlock(&xprt->reserve_lock);
 }
 
-static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
+static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
        return xprt->xid++;
 }
@@ -829,6 +821,7 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
        req->rq_bufsize = 0;
        req->rq_xid     = xprt_alloc_xid(xprt);
        req->rq_release_snd_buf = NULL;
+       xprt_reset_majortimeo(req);
        dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
                        req, ntohl(req->rq_xid));
 }
@@ -880,7 +873,7 @@ void xprt_release(struct rpc_task *task)
  */
 void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
 {
-       to->to_initval   = 
+       to->to_initval   =
        to->to_increment = incr;
        to->to_maxval    = to->to_initval + (incr * retr);
        to->to_retries   = retr;
@@ -897,47 +890,34 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
  */
 struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
 {
-       int result;
        struct rpc_xprt *xprt;
        struct rpc_rqst *req;
 
-       if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) {
-               dprintk("RPC:      xprt_create_transport: no memory\n");
-               return ERR_PTR(-ENOMEM);
-       }
-       if (size <= sizeof(xprt->addr)) {
-               memcpy(&xprt->addr, ap, size);
-               xprt->addrlen = size;
-       } else {
-               kfree(xprt);
-               dprintk("RPC:      xprt_create_transport: address too large\n");
-               return ERR_PTR(-EBADF);
-       }
-
        switch (proto) {
        case IPPROTO_UDP:
-               result = xs_setup_udp(xprt, to);
+               xprt = xs_setup_udp(ap, size, to);
                break;
        case IPPROTO_TCP:
-               result = xs_setup_tcp(xprt, to);
+               xprt = xs_setup_tcp(ap, size, to);
                break;
        default:
                printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
                                proto);
                return ERR_PTR(-EIO);
        }
-       if (result) {
-               kfree(xprt);
-               dprintk("RPC:      xprt_create_transport: failed, %d\n", result);
-               return ERR_PTR(result);
+       if (IS_ERR(xprt)) {
+               dprintk("RPC:      xprt_create_transport: failed, %ld\n",
+                               -PTR_ERR(xprt));
+               return xprt;
        }
 
+       kref_init(&xprt->kref);
        spin_lock_init(&xprt->transport_lock);
        spin_lock_init(&xprt->reserve_lock);
 
        INIT_LIST_HEAD(&xprt->free);
        INIT_LIST_HEAD(&xprt->recv);
-       INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
+       INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
        init_timer(&xprt->timer);
        xprt->timer.function = xprt_init_autodisconnect;
        xprt->timer.data = (unsigned long) xprt;
@@ -962,97 +942,42 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
        return xprt;
 }
 
-static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+/**
+ * xprt_destroy - destroy an RPC transport, killing off all requests.
+ * @kref: kref for the transport to destroy
+ *
+ */
+static void xprt_destroy(struct kref *kref)
 {
-       int result;
-       struct rpc_xprt *xprt;
-       struct rpc_rqst *req;
-
-       if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
-               return ERR_PTR(-ENOMEM);
+       struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
 
-       memcpy(&xprt->addr, ap, sizeof(*ap));
-       xprt->addrlen = sizeof(*ap);
-
-       switch (proto) {
-       case IPPROTO_UDP:
-               result = xs_setup_udp(xprt, to);
-               break;
-       case IPPROTO_TCP:
-               result = xs_setup_tcp(xprt, to);
-               break;
-       default:
-               printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
-                               proto);
-               result = -EIO;
-               break;
-       }
-       if (result) {
-               kfree(xprt);
-               return ERR_PTR(result);
-       }
-
-       spin_lock_init(&xprt->transport_lock);
-       spin_lock_init(&xprt->reserve_lock);
-
-       INIT_LIST_HEAD(&xprt->free);
-       INIT_LIST_HEAD(&xprt->recv);
-       INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
-       init_timer(&xprt->timer);
-       xprt->timer.function = xprt_init_autodisconnect;
-       xprt->timer.data = (unsigned long) xprt;
-       xprt->last_used = jiffies;
-       xprt->cwnd = RPC_INITCWND;
-
-       rpc_init_wait_queue(&xprt->binding, "xprt_binding");
-       rpc_init_wait_queue(&xprt->pending, "xprt_pending");
-       rpc_init_wait_queue(&xprt->sending, "xprt_sending");
-       rpc_init_wait_queue(&xprt->resend, "xprt_resend");
-       rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
-
-       /* initialize free list */
-       for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
-               list_add(&req->rq_list, &xprt->free);
-
-       xprt_init_xid(xprt);
+       dprintk("RPC:      destroying transport %p\n", xprt);
+       xprt->shutdown = 1;
+       del_timer_sync(&xprt->timer);
 
-       dprintk("RPC:      created transport %p with %u slots\n", xprt,
-                       xprt->max_reqs);
-       
-       return xprt;
+       /*
+        * Tear down transport state and free the rpc_xprt
+        */
+       xprt->ops->destroy(xprt);
 }
 
 /**
- * xprt_create_proto - create an RPC client transport
- * @proto: requested transport protocol
- * @sap: remote peer's address
- * @to: timeout parameters for new transport
+ * xprt_put - release a reference to an RPC transport.
+ * @xprt: pointer to the transport
  *
  */
-struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+void xprt_put(struct rpc_xprt *xprt)
 {
-       struct rpc_xprt *xprt;
-
-       xprt = xprt_setup(proto, sap, to);
-       if (IS_ERR(xprt))
-               dprintk("RPC:      xprt_create_proto failed\n");
-       else
-               dprintk("RPC:      xprt_create_proto created xprt %p\n", xprt);
-       return xprt;
+       kref_put(&xprt->kref, xprt_destroy);
 }
 
 /**
- * xprt_destroy - destroy an RPC transport, killing off all requests.
- * @xprt: transport to destroy
+ * xprt_get - return a reference to an RPC transport.
+ * @xprt: pointer to the transport
  *
  */
-int xprt_destroy(struct rpc_xprt *xprt)
+struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
 {
-       dprintk("RPC:      destroying transport %p\n", xprt);
-       xprt->shutdown = 1;
-       del_timer_sync(&xprt->timer);
-       xprt->ops->destroy(xprt);
-       kfree(xprt);
-
-       return 0;
+       kref_get(&xprt->kref);
+       return xprt;
 }