aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_cmd.c
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-09-27 18:07:25 -0400
committerRoland Dreier <rolandd@cisco.com>2005-10-17 18:20:25 -0400
commiteb9d3cd5ce2828fbb99ed7270089ea152c8f64b3 (patch)
tree2d0de42bc6c7777c66ee76d5817312bcfd161718 /drivers/infiniband/core/uverbs_cmd.c
parent6b73597e7062118c0549c2702bfb7d273518c906 (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>
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c111
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
291retry: 294retry:
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);
321err_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
330err_pd: 322 return in_len;
323
324err_idr:
325 idr_remove(&ib_uverbs_pd_idr, uobj->id);
326
327err_up:
328 up(&ib_uverbs_idr_mutex);
331 ib_dealloc_pd(pd); 329 ib_dealloc_pd(pd);
332 330
333err: 331err:
@@ -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
480err_list: 478err_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
485err_unreg: 481err_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
619retry: 617retry:
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);
650err_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
659err_cq: 646 return in_len;
647
648err_idr:
649 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
650
651err_up:
652 up(&ib_uverbs_idr_mutex);
660 ib_destroy_cq(cq); 653 ib_destroy_cq(cq);
661 654
662err: 655err:
@@ -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
854err_list: 847err_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
859err_destroy: 850err_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
1143err_list: 1134err_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
1148err_destroy: 1137err_destroy:
1149 ib_destroy_srq(srq); 1138 ib_destroy_srq(srq);