diff options
author | Tom Tucker <tom@opengridcomputing.com> | 2008-04-30 22:00:46 -0500 |
---|---|---|
committer | Tom Tucker <tom@opengridcomputing.com> | 2008-05-19 07:33:54 -0500 |
commit | 8da91ea8de873ee8be82377ff18637d05e882058 (patch) | |
tree | 9cfb692f27dde588a360a0f612b8ea14b04a76a4 /net | |
parent | 47698e083e40bbd3ef87f5561390ae33abb13cd0 (diff) | |
download | linux-3.10-8da91ea8de873ee8be82377ff18637d05e882058.tar.gz linux-3.10-8da91ea8de873ee8be82377ff18637d05e882058.tar.bz2 linux-3.10-8da91ea8de873ee8be82377ff18637d05e882058.zip |
svcrdma: Move destroy to kernel thread
Some providers may wait while destroying adapter resources.
Since it is possible that the last reference is put on the
dto_tasklet, the actual destroy must be scheduled as a work item.
Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 78303f0fad9..028c6cf8936 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -963,12 +963,15 @@ static void svc_rdma_detach(struct svc_xprt *xprt) rdma_destroy_id(rdma->sc_cm_id); } -static void svc_rdma_free(struct svc_xprt *xprt) +static void __svc_rdma_free(struct work_struct *work) { - struct svcxprt_rdma *rdma = (struct svcxprt_rdma *)xprt; + struct svcxprt_rdma *rdma = + container_of(work, struct svcxprt_rdma, sc_work); dprintk("svcrdma: svc_rdma_free(%p)\n", rdma); + /* We should only be called from kref_put */ - BUG_ON(atomic_read(&xprt->xpt_ref.refcount) != 0); + BUG_ON(atomic_read(&rdma->sc_xprt.xpt_ref.refcount) != 0); + if (rdma->sc_sq_cq && !IS_ERR(rdma->sc_sq_cq)) ib_destroy_cq(rdma->sc_sq_cq); @@ -985,6 +988,14 @@ static void svc_rdma_free(struct svc_xprt *xprt) kfree(rdma); } +static void svc_rdma_free(struct svc_xprt *xprt) +{ + struct svcxprt_rdma *rdma = + container_of(xprt, struct svcxprt_rdma, sc_xprt); + INIT_WORK(&rdma->sc_work, __svc_rdma_free); + schedule_work(&rdma->sc_work); +} + static int svc_rdma_has_wspace(struct svc_xprt *xprt) { struct svcxprt_rdma *rdma = |