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;
}
}
* @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;
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++;
}
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));
}
return ERR_PTR(result);
}
+ kref_init(&xprt->kref);
spin_lock_init(&xprt->transport_lock);
spin_lock_init(&xprt->reserve_lock);
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);
-
- 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);
+ struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
- xprt_init_xid(xprt);
-
- dprintk("RPC: created transport %p with %u slots\n", xprt,
- xprt->max_reqs);
-
- return xprt;
+ dprintk("RPC: destroying transport %p\n", xprt);
+ xprt->shutdown = 1;
+ del_timer_sync(&xprt->timer);
+ xprt->ops->destroy(xprt);
+ kfree(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;
}