On 08/05/2015 04:50 PM, Chuck Lever wrote:
> 
> On Aug 5, 2015, at 4:34 PM, Jason Gunthorpe <jguntho...@obsidianresearch.com> 
> wrote:
> 
>> The majority of callers never check the return value, and even if they
>> did, they can't do anything about a failure.
>>
>> All possible failure cases represent a bug in the caller, so just
>> WARN_ON inside the function instead.
>>
>> This fixes a few random errors:
>> net/rd/iw.c infinite loops while it fails. (racing with EBUSY?)
>>
>> This also lays the ground work to get rid of error return from the
>> drivers. Most drivers do not error, the few that do are broken since
>> it cannot be handled.
>>
>> Since uverbs can legitimately make use of EBUSY, open code the
>> check.
>>
>> Signed-off-by: Jason Gunthorpe <jguntho...@obsidianresearch.com>
>> ---
>> drivers/infiniband/core/uverbs_cmd.c       | 22 ++++++++++++++++------
>> drivers/infiniband/core/verbs.c            | 26 ++++++++++++++++++++------
>> drivers/infiniband/ulp/ipoib/ipoib_verbs.c |  4 +---
>> drivers/infiniband/ulp/iser/iser_verbs.c   |  2 +-
>> include/rdma/ib_verbs.h                    |  6 +-----
>> net/rds/iw.c                               |  5 +----
>> net/sunrpc/xprtrdma/verbs.c                |  2 +-
>> 7 files changed, 41 insertions(+), 26 deletions(-)
>>
>> Doug, this applies after the local_dma_lkey cleanup series.
>>
>> Lightly tested with ipoib/uverbs/umad on mlx4.
>>
>> This patch will expose buggy ULPs, I would not be too surprised to see
>> a report of the WARN_ON triggering...
>>
>> diff --git a/drivers/infiniband/core/uverbs_cmd.c 
>> b/drivers/infiniband/core/uverbs_cmd.c
>> index 258485ee46b2..4c98696e3626 100644
>> --- a/drivers/infiniband/core/uverbs_cmd.c
>> +++ b/drivers/infiniband/core/uverbs_cmd.c
>> @@ -606,6 +606,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
>> {
>>      struct ib_uverbs_dealloc_pd cmd;
>>      struct ib_uobject          *uobj;
>> +    struct ib_pd               *pd;
>>      int                         ret;
>>
>>      if (copy_from_user(&cmd, buf, sizeof cmd))
>> @@ -614,15 +615,20 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file 
>> *file,
>>      uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext);
>>      if (!uobj)
>>              return -EINVAL;
>> +    pd = uobj->object;
>>
>> -    ret = ib_dealloc_pd(uobj->object);
>> -    if (!ret)
>> -            uobj->live = 0;
>> -
>> -    put_uobj_write(uobj);
>> +    if (atomic_read(&pd->usecnt)) {
>> +            ret = -EBUSY;
>> +            goto err_put;
>> +    }
>>
>> +    ret = pd->device->dealloc_pd(uobj->object);
>> +    WARN_ONCE(ret, "Infiniband HW driver failed dealloc_pd");
>>      if (ret)
>> -            return ret;
>> +            goto err_put;
>> +
>> +    uobj->live = 0;
>> +    put_uobj_write(uobj);
>>
>>      idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
>>
>> @@ -633,6 +639,10 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file 
>> *file,
>>      put_uobj(uobj);
>>
>>      return in_len;
>> +
>> +err_put:
>> +    put_uobj_write(uobj);
>> +    return ret;
>> }
>>
>> struct xrcd_table_entry {
>> diff --git a/drivers/infiniband/core/verbs.c 
>> b/drivers/infiniband/core/verbs.c
>> index bb561c8e51ad..b13f7a9240b5 100644
>> --- a/drivers/infiniband/core/verbs.c
>> +++ b/drivers/infiniband/core/verbs.c
>> @@ -260,18 +260,32 @@ struct ib_pd *ib_alloc_pd(struct ib_device *device)
>> }
>> EXPORT_SYMBOL(ib_alloc_pd);
>>
>> -int ib_dealloc_pd(struct ib_pd *pd)
>> +/**
>> + * ib_dealloc_pd - Deallocates a protection domain.
>> + * @pd: The protection domain to deallocate.
>> + *
>> + * It is an error to call this function while any resources in the pd still
>> + * exist.  The caller is responsible to synchronously destroy them and
>> + * guarantee no new allocations will happen.
>> + */
>> +void ib_dealloc_pd(struct ib_pd *pd)
>> {
>> +    int ret;
>> +
>>      if (pd->local_mr) {
>> -            if (ib_dereg_mr(pd->local_mr))
>> -                    return -EBUSY;
>> +            ret = ib_dereg_mr(pd->local_mr);
>> +            WARN_ON(ret);
>>              pd->local_mr = NULL;
>>      }
>>
>> -    if (atomic_read(&pd->usecnt))
>> -            return -EBUSY;
>> +    /* uverbs manipulates usecnt with proper locking, while the kabi
>> +       requires the caller to guarantee we can't race here. */
>> +    WARN_ON(atomic_read(&pd->usecnt));
>>
>> -    return pd->device->dealloc_pd(pd);
>> +    /* Making delalloc_pd a void return is a WIP, no driver should return
>> +       an error here. */
>> +    ret = pd->device->dealloc_pd(pd);
>> +    WARN_ONCE(ret, "Infiniband HW driver failed dealloc_pd");
>> }
>> EXPORT_SYMBOL(ib_dealloc_pd);
>>
>> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c 
>> b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
>> index 8c451983d8a5..78845b6e8b81 100644
>> --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
>> +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
>> @@ -280,9 +280,7 @@ void ipoib_transport_dev_cleanup(struct net_device *dev)
>>              priv->wq = NULL;
>>      }
>>
>> -    if (ib_dealloc_pd(priv->pd))
>> -            ipoib_warn(priv, "ib_dealloc_pd failed\n");
>> -
>> +    ib_dealloc_pd(priv->pd);
>> }
>>
>> void ipoib_event(struct ib_event_handler *handler,
>> diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c 
>> b/drivers/infiniband/ulp/iser/iser_verbs.c
>> index 52268356c79e..6e984e4b553b 100644
>> --- a/drivers/infiniband/ulp/iser/iser_verbs.c
>> +++ b/drivers/infiniband/ulp/iser/iser_verbs.c
>> @@ -201,7 +201,7 @@ static void iser_free_device_ib_res(struct iser_device 
>> *device)
>>
>>      (void)ib_unregister_event_handler(&device->event_handler);
>>      (void)ib_dereg_mr(device->mr);
>> -    (void)ib_dealloc_pd(device->pd);
>> +    ib_dealloc_pd(device->pd);
>>
>>      kfree(device->comps);
>>      device->comps = NULL;
>> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
>> index eaec3081fb87..4aaab4fe459c 100644
>> --- a/include/rdma/ib_verbs.h
>> +++ b/include/rdma/ib_verbs.h
>> @@ -2139,11 +2139,7 @@ int ib_find_pkey(struct ib_device *device,
>>
>> struct ib_pd *ib_alloc_pd(struct ib_device *device);
>>
>> -/**
>> - * ib_dealloc_pd - Deallocates a protection domain.
>> - * @pd: The protection domain to deallocate.
>> - */
>> -int ib_dealloc_pd(struct ib_pd *pd);
>> +void ib_dealloc_pd(struct ib_pd *pd);
>>
>> /**
>>  * ib_create_ah - Creates an address handle for the given address vector.
>> diff --git a/net/rds/iw.c b/net/rds/iw.c
>> index 589935661d66..5f228e00ad09 100644
>> --- a/net/rds/iw.c
>> +++ b/net/rds/iw.c
>> @@ -149,10 +149,7 @@ static void rds_iw_remove_one(struct ib_device *device)
>>      if (rds_iwdev->mr)
>>              ib_dereg_mr(rds_iwdev->mr);
>>
>> -    while (ib_dealloc_pd(rds_iwdev->pd)) {
>> -            rdsdebug("Failed to dealloc pd %p\n", rds_iwdev->pd);
>> -            msleep(1);
>> -    }
>> +    ib_dealloc_pd(rds_iwdev->pd);
>>
>>      list_del(&rds_iwdev->list);
>>      kfree(rds_iwdev);
>> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
>> index 891c4ede2c20..afd504375a9a 100644
>> --- a/net/sunrpc/xprtrdma/verbs.c
>> +++ b/net/sunrpc/xprtrdma/verbs.c
>> @@ -624,7 +624,7 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
>>
>>      /* If the pd is still busy, xprtrdma missed freeing a resource */
>>      if (ia->ri_pd && !IS_ERR(ia->ri_pd))
>> -            WARN_ON(ib_dealloc_pd(ia->ri_pd));
>> +            ib_dealloc_pd(ia->ri_pd);
>> }
>>
>> /*
> 
> Reviewed-by: Chuck Lever <chuck.le...@oracle.com>
> 
> Does this hunk or the xprtrdma changes in the local DMA lkey
> series need an Acked-by: from Anna?

If it's a client side change, then yeah it'll need an Acked-by from me.  I'm 
not sure if I've seen the DMA lkey changes yet, can somebody point me to them?

This hunk looks fine to me:

        Acked-by: Anna Schumaker <anna.schuma...@netapp.com>

Thanks,
Anna

> 
> 
> --
> Chuck Lever
> 
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to