Commit eb9d3cd5 authored by Roland Dreier's avatar Roland Dreier

[IB] uverbs: Fix up resource creation error paths

By waiting to add resources to our lists until after the last
operation that can fail, we don't have to remove them from their lists
in the error path.  Also, we should hold the idr mutex until we know
whether resource creation has succeed or failed, to avoid someone
finding a resource in our table before we're ready.

Loosely based on work by Robert Walsh <rjwalsh@pathscale.com>.
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 6b73597e
/* /*
* Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved. * Copyright (c) 2005 Cisco Systems. All rights reserved.
* Copyright (c) 2005 PathScale, Inc. All rights reserved.
* *
* This software is available to you under a choice of one of two * This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU * licenses. You may choose to be licensed under the terms of the GNU
...@@ -288,24 +289,20 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, ...@@ -288,24 +289,20 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
pd->uobject = uobj; pd->uobject = uobj;
atomic_set(&pd->usecnt, 0); atomic_set(&pd->usecnt, 0);
down(&ib_uverbs_idr_mutex);
retry: retry:
if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_pd; goto err_up;
} }
down(&ib_uverbs_idr_mutex);
ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
up(&ib_uverbs_idr_mutex);
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto retry; goto retry;
if (ret) if (ret)
goto err_pd; goto err_up;
down(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
up(&file->mutex);
memset(&resp, 0, sizeof resp); memset(&resp, 0, sizeof resp);
resp.pd_handle = uobj->id; resp.pd_handle = uobj->id;
...@@ -313,21 +310,22 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, ...@@ -313,21 +310,22 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
ret = -EFAULT; ret = -EFAULT;
goto err_list; goto err_idr;
} }
return in_len; down(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
err_list:
down(&file->mutex);
list_del(&uobj->list);
up(&file->mutex); up(&file->mutex);
down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_pd_idr, uobj->id);
up(&ib_uverbs_idr_mutex); up(&ib_uverbs_idr_mutex);
err_pd: return in_len;
err_idr:
idr_remove(&ib_uverbs_pd_idr, uobj->id);
err_up:
up(&ib_uverbs_idr_mutex);
ib_dealloc_pd(pd); ib_dealloc_pd(pd);
err: err:
...@@ -463,24 +461,22 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, ...@@ -463,24 +461,22 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
resp.mr_handle = obj->uobject.id; resp.mr_handle = obj->uobject.id;
down(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
ret = -EFAULT; ret = -EFAULT;
goto err_list; goto err_idr;
} }
down(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
up(&file->mutex);
up(&ib_uverbs_idr_mutex); up(&ib_uverbs_idr_mutex);
return in_len; return in_len;
err_list: err_idr:
down(&file->mutex); idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
list_del(&obj->uobject.list);
up(&file->mutex);
err_unreg: err_unreg:
ib_dereg_mr(mr); ib_dereg_mr(mr);
...@@ -616,24 +612,20 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, ...@@ -616,24 +612,20 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
cq->cq_context = ev_file; cq->cq_context = ev_file;
atomic_set(&cq->usecnt, 0); atomic_set(&cq->usecnt, 0);
down(&ib_uverbs_idr_mutex);
retry: retry:
if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_cq; goto err_up;
} }
down(&ib_uverbs_idr_mutex);
ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
up(&ib_uverbs_idr_mutex);
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto retry; goto retry;
if (ret) if (ret)
goto err_cq; goto err_up;
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
up(&file->mutex);
memset(&resp, 0, sizeof resp); memset(&resp, 0, sizeof resp);
resp.cq_handle = uobj->uobject.id; resp.cq_handle = uobj->uobject.id;
...@@ -642,21 +634,22 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, ...@@ -642,21 +634,22 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
ret = -EFAULT; ret = -EFAULT;
goto err_list; goto err_idr;
} }
return in_len; down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
err_list:
down(&file->mutex);
list_del(&uobj->uobject.list);
up(&file->mutex); up(&file->mutex);
down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
up(&ib_uverbs_idr_mutex); up(&ib_uverbs_idr_mutex);
err_cq: return in_len;
err_idr:
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
err_up:
up(&ib_uverbs_idr_mutex);
ib_destroy_cq(cq); ib_destroy_cq(cq);
err: err:
...@@ -837,24 +830,22 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, ...@@ -837,24 +830,22 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
resp.qp_handle = uobj->uobject.id; resp.qp_handle = uobj->uobject.id;
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
ret = -EFAULT; ret = -EFAULT;
goto err_list; goto err_idr;
} }
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
up(&file->mutex);
up(&ib_uverbs_idr_mutex); up(&ib_uverbs_idr_mutex);
return in_len; return in_len;
err_list: err_idr:
down(&file->mutex); idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);
list_del(&uobj->uobject.list);
up(&file->mutex);
err_destroy: err_destroy:
ib_destroy_qp(qp); ib_destroy_qp(qp);
...@@ -1126,24 +1117,22 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, ...@@ -1126,24 +1117,22 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
resp.srq_handle = uobj->uobject.id; resp.srq_handle = uobj->uobject.id;
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response, if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) { &resp, sizeof resp)) {
ret = -EFAULT; ret = -EFAULT;
goto err_list; goto err_idr;
} }
down(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
up(&file->mutex);
up(&ib_uverbs_idr_mutex); up(&ib_uverbs_idr_mutex);
return in_len; return in_len;
err_list: err_idr:
down(&file->mutex); idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
list_del(&uobj->uobject.list);
up(&file->mutex);
err_destroy: err_destroy:
ib_destroy_srq(srq); ib_destroy_srq(srq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment