diff options
author | Roland Dreier <rolandd@cisco.com> | 2005-09-27 18:07:25 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2005-10-17 18:20:25 -0400 |
commit | eb9d3cd5ce2828fbb99ed7270089ea152c8f64b3 (patch) | |
tree | 2d0de42bc6c7777c66ee76d5817312bcfd161718 | |
parent | 6b73597e7062118c0549c2702bfb7d273518c906 (diff) |
[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: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 111 |
1 files changed, 50 insertions, 61 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 79b60c3dc8d0..a0ceb1cbed52 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Cisco Systems. All rights reserved. | 3 | * Copyright (c) 2005 Cisco Systems. All rights reserved. |
4 | * Copyright (c) 2005 PathScale, Inc. All rights reserved. | ||
4 | * | 5 | * |
5 | * This software is available to you under a choice of one of two | 6 | * This software is available to you under a choice of one of two |
6 | * licenses. You may choose to be licensed under the terms of the GNU | 7 | * 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 | pd->uobject = uobj; | 289 | pd->uobject = uobj; |
289 | atomic_set(&pd->usecnt, 0); | 290 | atomic_set(&pd->usecnt, 0); |
290 | 291 | ||
292 | down(&ib_uverbs_idr_mutex); | ||
293 | |||
291 | retry: | 294 | retry: |
292 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { | 295 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { |
293 | ret = -ENOMEM; | 296 | ret = -ENOMEM; |
294 | goto err_pd; | 297 | goto err_up; |
295 | } | 298 | } |
296 | 299 | ||
297 | down(&ib_uverbs_idr_mutex); | ||
298 | ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); | 300 | ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); |
299 | up(&ib_uverbs_idr_mutex); | ||
300 | 301 | ||
301 | if (ret == -EAGAIN) | 302 | if (ret == -EAGAIN) |
302 | goto retry; | 303 | goto retry; |
303 | if (ret) | 304 | if (ret) |
304 | goto err_pd; | 305 | goto err_up; |
305 | |||
306 | down(&file->mutex); | ||
307 | list_add_tail(&uobj->list, &file->ucontext->pd_list); | ||
308 | up(&file->mutex); | ||
309 | 306 | ||
310 | memset(&resp, 0, sizeof resp); | 307 | memset(&resp, 0, sizeof resp); |
311 | resp.pd_handle = uobj->id; | 308 | resp.pd_handle = uobj->id; |
@@ -313,21 +310,22 @@ retry: | |||
313 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 310 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
314 | &resp, sizeof resp)) { | 311 | &resp, sizeof resp)) { |
315 | ret = -EFAULT; | 312 | ret = -EFAULT; |
316 | goto err_list; | 313 | goto err_idr; |
317 | } | 314 | } |
318 | 315 | ||
319 | return in_len; | 316 | down(&file->mutex); |
320 | 317 | list_add_tail(&uobj->list, &file->ucontext->pd_list); | |
321 | err_list: | ||
322 | down(&file->mutex); | ||
323 | list_del(&uobj->list); | ||
324 | up(&file->mutex); | 318 | up(&file->mutex); |
325 | 319 | ||
326 | down(&ib_uverbs_idr_mutex); | ||
327 | idr_remove(&ib_uverbs_pd_idr, uobj->id); | ||
328 | up(&ib_uverbs_idr_mutex); | 320 | up(&ib_uverbs_idr_mutex); |
329 | 321 | ||
330 | err_pd: | 322 | return in_len; |
323 | |||
324 | err_idr: | ||
325 | idr_remove(&ib_uverbs_pd_idr, uobj->id); | ||
326 | |||
327 | err_up: | ||
328 | up(&ib_uverbs_idr_mutex); | ||
331 | ib_dealloc_pd(pd); | 329 | ib_dealloc_pd(pd); |
332 | 330 | ||
333 | err: | 331 | err: |
@@ -463,24 +461,22 @@ retry: | |||
463 | 461 | ||
464 | resp.mr_handle = obj->uobject.id; | 462 | resp.mr_handle = obj->uobject.id; |
465 | 463 | ||
466 | down(&file->mutex); | ||
467 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); | ||
468 | up(&file->mutex); | ||
469 | |||
470 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 464 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
471 | &resp, sizeof resp)) { | 465 | &resp, sizeof resp)) { |
472 | ret = -EFAULT; | 466 | ret = -EFAULT; |
473 | goto err_list; | 467 | goto err_idr; |
474 | } | 468 | } |
475 | 469 | ||
470 | down(&file->mutex); | ||
471 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); | ||
472 | up(&file->mutex); | ||
473 | |||
476 | up(&ib_uverbs_idr_mutex); | 474 | up(&ib_uverbs_idr_mutex); |
477 | 475 | ||
478 | return in_len; | 476 | return in_len; |
479 | 477 | ||
480 | err_list: | 478 | err_idr: |
481 | down(&file->mutex); | 479 | idr_remove(&ib_uverbs_mr_idr, obj->uobject.id); |
482 | list_del(&obj->uobject.list); | ||
483 | up(&file->mutex); | ||
484 | 480 | ||
485 | err_unreg: | 481 | err_unreg: |
486 | ib_dereg_mr(mr); | 482 | ib_dereg_mr(mr); |
@@ -616,24 +612,20 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
616 | cq->cq_context = ev_file; | 612 | cq->cq_context = ev_file; |
617 | atomic_set(&cq->usecnt, 0); | 613 | atomic_set(&cq->usecnt, 0); |
618 | 614 | ||
615 | down(&ib_uverbs_idr_mutex); | ||
616 | |||
619 | retry: | 617 | retry: |
620 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { | 618 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { |
621 | ret = -ENOMEM; | 619 | ret = -ENOMEM; |
622 | goto err_cq; | 620 | goto err_up; |
623 | } | 621 | } |
624 | 622 | ||
625 | down(&ib_uverbs_idr_mutex); | ||
626 | ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); | 623 | ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); |
627 | up(&ib_uverbs_idr_mutex); | ||
628 | 624 | ||
629 | if (ret == -EAGAIN) | 625 | if (ret == -EAGAIN) |
630 | goto retry; | 626 | goto retry; |
631 | if (ret) | 627 | if (ret) |
632 | goto err_cq; | 628 | goto err_up; |
633 | |||
634 | down(&file->mutex); | ||
635 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); | ||
636 | up(&file->mutex); | ||
637 | 629 | ||
638 | memset(&resp, 0, sizeof resp); | 630 | memset(&resp, 0, sizeof resp); |
639 | resp.cq_handle = uobj->uobject.id; | 631 | resp.cq_handle = uobj->uobject.id; |
@@ -642,21 +634,22 @@ retry: | |||
642 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 634 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
643 | &resp, sizeof resp)) { | 635 | &resp, sizeof resp)) { |
644 | ret = -EFAULT; | 636 | ret = -EFAULT; |
645 | goto err_list; | 637 | goto err_idr; |
646 | } | 638 | } |
647 | 639 | ||
648 | return in_len; | 640 | down(&file->mutex); |
649 | 641 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); | |
650 | err_list: | ||
651 | down(&file->mutex); | ||
652 | list_del(&uobj->uobject.list); | ||
653 | up(&file->mutex); | 642 | up(&file->mutex); |
654 | 643 | ||
655 | down(&ib_uverbs_idr_mutex); | ||
656 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); | ||
657 | up(&ib_uverbs_idr_mutex); | 644 | up(&ib_uverbs_idr_mutex); |
658 | 645 | ||
659 | err_cq: | 646 | return in_len; |
647 | |||
648 | err_idr: | ||
649 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); | ||
650 | |||
651 | err_up: | ||
652 | up(&ib_uverbs_idr_mutex); | ||
660 | ib_destroy_cq(cq); | 653 | ib_destroy_cq(cq); |
661 | 654 | ||
662 | err: | 655 | err: |
@@ -837,24 +830,22 @@ retry: | |||
837 | 830 | ||
838 | resp.qp_handle = uobj->uobject.id; | 831 | resp.qp_handle = uobj->uobject.id; |
839 | 832 | ||
840 | down(&file->mutex); | ||
841 | list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); | ||
842 | up(&file->mutex); | ||
843 | |||
844 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 833 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
845 | &resp, sizeof resp)) { | 834 | &resp, sizeof resp)) { |
846 | ret = -EFAULT; | 835 | ret = -EFAULT; |
847 | goto err_list; | 836 | goto err_idr; |
848 | } | 837 | } |
849 | 838 | ||
839 | down(&file->mutex); | ||
840 | list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); | ||
841 | up(&file->mutex); | ||
842 | |||
850 | up(&ib_uverbs_idr_mutex); | 843 | up(&ib_uverbs_idr_mutex); |
851 | 844 | ||
852 | return in_len; | 845 | return in_len; |
853 | 846 | ||
854 | err_list: | 847 | err_idr: |
855 | down(&file->mutex); | 848 | idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id); |
856 | list_del(&uobj->uobject.list); | ||
857 | up(&file->mutex); | ||
858 | 849 | ||
859 | err_destroy: | 850 | err_destroy: |
860 | ib_destroy_qp(qp); | 851 | ib_destroy_qp(qp); |
@@ -1126,24 +1117,22 @@ retry: | |||
1126 | 1117 | ||
1127 | resp.srq_handle = uobj->uobject.id; | 1118 | resp.srq_handle = uobj->uobject.id; |
1128 | 1119 | ||
1129 | down(&file->mutex); | ||
1130 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); | ||
1131 | up(&file->mutex); | ||
1132 | |||
1133 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 1120 | if (copy_to_user((void __user *) (unsigned long) cmd.response, |
1134 | &resp, sizeof resp)) { | 1121 | &resp, sizeof resp)) { |
1135 | ret = -EFAULT; | 1122 | ret = -EFAULT; |
1136 | goto err_list; | 1123 | goto err_idr; |
1137 | } | 1124 | } |
1138 | 1125 | ||
1126 | down(&file->mutex); | ||
1127 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); | ||
1128 | up(&file->mutex); | ||
1129 | |||
1139 | up(&ib_uverbs_idr_mutex); | 1130 | up(&ib_uverbs_idr_mutex); |
1140 | 1131 | ||
1141 | return in_len; | 1132 | return in_len; |
1142 | 1133 | ||
1143 | err_list: | 1134 | err_idr: |
1144 | down(&file->mutex); | 1135 | idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id); |
1145 | list_del(&uobj->uobject.list); | ||
1146 | up(&file->mutex); | ||
1147 | 1136 | ||
1148 | err_destroy: | 1137 | err_destroy: |
1149 | ib_destroy_srq(srq); | 1138 | ib_destroy_srq(srq); |