svcrdma: Move destroy to kernel thread
authorTom Tucker <tom@opengridcomputing.com>
Thu, 1 May 2008 03:00:46 +0000 (22:00 -0500)
committerTom Tucker <tom@opengridcomputing.com>
Mon, 19 May 2008 12:33:54 +0000 (07:33 -0500)
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>
include/linux/sunrpc/svc_rdma.h
net/sunrpc/xprtrdma/svc_rdma_transport.c

index 701439064d2134db35ea4bc730786cb04616a536..f5f15ae2438b8b452e91b28ff5bc4ce7343176c8 100644 (file)
@@ -124,6 +124,7 @@ struct svcxprt_rdma {
        struct list_head     sc_dto_q;          /* DTO tasklet I/O pending Q */
        struct list_head     sc_read_complete_q;
        spinlock_t           sc_read_complete_lock;
+       struct work_struct   sc_work;
 };
 /* sc_flags */
 #define RDMAXPRT_RQ_PENDING    1
index 78303f0fad927117aa5d02b789804573f9460039..028c6cf89364139f14b2c59afe2dd3ef09480f38 100644 (file)
@@ -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 =