Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/uverbs: Don't serialize with ib_uverbs_idr_mutex

Currently, all userspace verbs operations that call into the kernel
are serialized by ib_uverbs_idr_mutex. This can be a scalability
issue for some workloads, especially for devices driven by the ipath
driver, which needs to call into the kernel even for datapath
operations.

Fix this by adding reference counts to the userspace objects, and then
converting ib_uverbs_idr_mutex into a spinlock that only protects the
idrs long enough to take a reference on the object being looked up.
Because remove operations may fail, we have to do a slightly funky
two-step deletion, which is described in the comments at the top of
uverbs_cmd.c.

This also still leaves ib_uverbs_idr_lock as a single lock that is
possibly subject to contention. However, the lock hold time will only
be a single idr operation, so multiple threads should still be able to
make progress, even if ib_uverbs_idr_lock is being ping-ponged.

Surprisingly, these changes even shrink the object code:

add/remove: 23/5 grow/shrink: 4/21 up/down: 633/-693 (-60)

Signed-off-by: Roland Dreier <rolandd@cisco.com>

+564 -383
+3 -1
drivers/infiniband/core/uverbs.h
··· 132 132 u32 async_events_reported; 133 133 }; 134 134 135 - extern struct mutex ib_uverbs_idr_mutex; 135 + extern spinlock_t ib_uverbs_idr_lock; 136 136 extern struct idr ib_uverbs_pd_idr; 137 137 extern struct idr ib_uverbs_mr_idr; 138 138 extern struct idr ib_uverbs_mw_idr; ··· 140 140 extern struct idr ib_uverbs_cq_idr; 141 141 extern struct idr ib_uverbs_qp_idr; 142 142 extern struct idr ib_uverbs_srq_idr; 143 + 144 + void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj); 143 145 144 146 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, 145 147 int is_async, int *fd);
+539 -365
drivers/infiniband/core/uverbs_cmd.c
··· 50 50 (udata)->outlen = (olen); \ 51 51 } while (0) 52 52 53 - static int idr_add_uobj(struct idr *idr, void *obj, struct ib_uobject *uobj) 53 + /* 54 + * The ib_uobject locking scheme is as follows: 55 + * 56 + * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it 57 + * needs to be held during all idr operations. When an object is 58 + * looked up, a reference must be taken on the object's kref before 59 + * dropping this lock. 60 + * 61 + * - Each object also has an rwsem. This rwsem must be held for 62 + * reading while an operation that uses the object is performed. 63 + * For example, while registering an MR, the associated PD's 64 + * uobject.mutex must be held for reading. The rwsem must be held 65 + * for writing while initializing or destroying an object. 66 + * 67 + * - In addition, each object has a "live" flag. If this flag is not 68 + * set, then lookups of the object will fail even if it is found in 69 + * the idr. This handles a reader that blocks and does not acquire 70 + * the rwsem until after the object is destroyed. The destroy 71 + * operation will set the live flag to 0 and then drop the rwsem; 72 + * this will allow the reader to acquire the rwsem, see that the 73 + * live flag is 0, and then drop the rwsem and its reference to 74 + * object. The underlying storage will not be freed until the last 75 + * reference to the object is dropped. 76 + */ 77 + 78 + static void init_uobj(struct ib_uobject *uobj, u64 user_handle, 79 + struct ib_ucontext *context) 80 + { 81 + uobj->user_handle = user_handle; 82 + uobj->context = context; 83 + kref_init(&uobj->ref); 84 + init_rwsem(&uobj->mutex); 85 + uobj->live = 0; 86 + } 87 + 88 + static void release_uobj(struct kref *kref) 89 + { 90 + kfree(container_of(kref, struct ib_uobject, ref)); 91 + } 92 + 93 + static void put_uobj(struct ib_uobject *uobj) 94 + { 95 + kref_put(&uobj->ref, release_uobj); 96 + } 97 + 98 + static void put_uobj_read(struct ib_uobject *uobj) 99 + { 100 + up_read(&uobj->mutex); 101 + put_uobj(uobj); 102 + } 103 + 104 + static void put_uobj_write(struct ib_uobject *uobj) 105 + { 106 + up_write(&uobj->mutex); 107 + put_uobj(uobj); 108 + } 109 + 110 + static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj) 54 111 { 55 112 int ret; 56 113 ··· 115 58 if (!idr_pre_get(idr, GFP_KERNEL)) 116 59 return -ENOMEM; 117 60 61 + spin_lock(&ib_uverbs_idr_lock); 118 62 ret = idr_get_new(idr, uobj, &uobj->id); 63 + spin_unlock(&ib_uverbs_idr_lock); 119 64 120 65 if (ret == -EAGAIN) 121 66 goto retry; 122 67 123 68 return ret; 69 + } 70 + 71 + void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj) 72 + { 73 + spin_lock(&ib_uverbs_idr_lock); 74 + idr_remove(idr, uobj->id); 75 + spin_unlock(&ib_uverbs_idr_lock); 76 + } 77 + 78 + static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id, 79 + struct ib_ucontext *context) 80 + { 81 + struct ib_uobject *uobj; 82 + 83 + spin_lock(&ib_uverbs_idr_lock); 84 + uobj = idr_find(idr, id); 85 + if (uobj) 86 + kref_get(&uobj->ref); 87 + spin_unlock(&ib_uverbs_idr_lock); 88 + 89 + return uobj; 90 + } 91 + 92 + static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, 93 + struct ib_ucontext *context) 94 + { 95 + struct ib_uobject *uobj; 96 + 97 + uobj = __idr_get_uobj(idr, id, context); 98 + if (!uobj) 99 + return NULL; 100 + 101 + down_read(&uobj->mutex); 102 + if (!uobj->live) { 103 + put_uobj_read(uobj); 104 + return NULL; 105 + } 106 + 107 + return uobj; 108 + } 109 + 110 + static struct ib_uobject *idr_write_uobj(struct idr *idr, int id, 111 + struct ib_ucontext *context) 112 + { 113 + struct ib_uobject *uobj; 114 + 115 + uobj = __idr_get_uobj(idr, id, context); 116 + if (!uobj) 117 + return NULL; 118 + 119 + down_write(&uobj->mutex); 120 + if (!uobj->live) { 121 + put_uobj_write(uobj); 122 + return NULL; 123 + } 124 + 125 + return uobj; 126 + } 127 + 128 + static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context) 129 + { 130 + struct ib_uobject *uobj; 131 + 132 + uobj = idr_read_uobj(idr, id, context); 133 + return uobj ? uobj->object : NULL; 134 + } 135 + 136 + static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) 137 + { 138 + return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context); 139 + } 140 + 141 + static void put_pd_read(struct ib_pd *pd) 142 + { 143 + put_uobj_read(pd->uobject); 144 + } 145 + 146 + static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context) 147 + { 148 + return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context); 149 + } 150 + 151 + static void put_cq_read(struct ib_cq *cq) 152 + { 153 + put_uobj_read(cq->uobject); 154 + } 155 + 156 + static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) 157 + { 158 + return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context); 159 + } 160 + 161 + static void put_ah_read(struct ib_ah *ah) 162 + { 163 + put_uobj_read(ah->uobject); 164 + } 165 + 166 + static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) 167 + { 168 + return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context); 169 + } 170 + 171 + static void put_qp_read(struct ib_qp *qp) 172 + { 173 + put_uobj_read(qp->uobject); 174 + } 175 + 176 + static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) 177 + { 178 + return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context); 179 + } 180 + 181 + static void put_srq_read(struct ib_srq *srq) 182 + { 183 + put_uobj_read(srq->uobject); 124 184 } 125 185 126 186 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, ··· 470 296 if (!uobj) 471 297 return -ENOMEM; 472 298 473 - uobj->context = file->ucontext; 299 + init_uobj(uobj, 0, file->ucontext); 300 + down_write(&uobj->mutex); 474 301 475 302 pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, 476 303 file->ucontext, &udata); ··· 484 309 pd->uobject = uobj; 485 310 atomic_set(&pd->usecnt, 0); 486 311 487 - mutex_lock(&ib_uverbs_idr_mutex); 488 - 489 - ret = idr_add_uobj(&ib_uverbs_pd_idr, pd, uobj); 312 + uobj->object = pd; 313 + ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj); 490 314 if (ret) 491 - goto err_up; 315 + goto err_idr; 492 316 493 317 memset(&resp, 0, sizeof resp); 494 318 resp.pd_handle = uobj->id; ··· 495 321 if (copy_to_user((void __user *) (unsigned long) cmd.response, 496 322 &resp, sizeof resp)) { 497 323 ret = -EFAULT; 498 - goto err_idr; 324 + goto err_copy; 499 325 } 500 326 501 327 mutex_lock(&file->mutex); 502 328 list_add_tail(&uobj->list, &file->ucontext->pd_list); 503 329 mutex_unlock(&file->mutex); 504 330 505 - mutex_unlock(&ib_uverbs_idr_mutex); 331 + uobj->live = 1; 332 + 333 + up_write(&uobj->mutex); 506 334 507 335 return in_len; 508 336 509 - err_idr: 510 - idr_remove(&ib_uverbs_pd_idr, uobj->id); 337 + err_copy: 338 + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); 511 339 512 - err_up: 513 - mutex_unlock(&ib_uverbs_idr_mutex); 340 + err_idr: 514 341 ib_dealloc_pd(pd); 515 342 516 343 err: 517 - kfree(uobj); 344 + put_uobj_write(uobj); 518 345 return ret; 519 346 } 520 347 ··· 524 349 int in_len, int out_len) 525 350 { 526 351 struct ib_uverbs_dealloc_pd cmd; 527 - struct ib_pd *pd; 528 352 struct ib_uobject *uobj; 529 - int ret = -EINVAL; 353 + int ret; 530 354 531 355 if (copy_from_user(&cmd, buf, sizeof cmd)) 532 356 return -EFAULT; 533 357 534 - mutex_lock(&ib_uverbs_idr_mutex); 358 + uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext); 359 + if (!uobj) 360 + return -EINVAL; 535 361 536 - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 537 - if (!pd || pd->uobject->context != file->ucontext) 538 - goto out; 362 + ret = ib_dealloc_pd(uobj->object); 363 + if (!ret) 364 + uobj->live = 0; 539 365 540 - uobj = pd->uobject; 366 + put_uobj_write(uobj); 541 367 542 - ret = ib_dealloc_pd(pd); 543 368 if (ret) 544 - goto out; 369 + return ret; 545 370 546 - idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); 371 + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); 547 372 548 373 mutex_lock(&file->mutex); 549 374 list_del(&uobj->list); 550 375 mutex_unlock(&file->mutex); 551 376 552 - kfree(uobj); 377 + put_uobj(uobj); 553 378 554 - out: 555 - mutex_unlock(&ib_uverbs_idr_mutex); 556 - 557 - return ret ? ret : in_len; 379 + return in_len; 558 380 } 559 381 560 382 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, ··· 591 419 if (!obj) 592 420 return -ENOMEM; 593 421 594 - obj->uobject.context = file->ucontext; 422 + init_uobj(&obj->uobject, 0, file->ucontext); 423 + down_write(&obj->uobject.mutex); 595 424 596 425 /* 597 426 * We ask for writable memory if any access flags other than ··· 609 436 610 437 obj->umem.virt_base = cmd.hca_va; 611 438 612 - mutex_lock(&ib_uverbs_idr_mutex); 613 - 614 - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 615 - if (!pd || pd->uobject->context != file->ucontext) { 616 - ret = -EINVAL; 617 - goto err_up; 618 - } 619 - 620 - if (!pd->device->reg_user_mr) { 621 - ret = -ENOSYS; 622 - goto err_up; 623 - } 439 + pd = idr_read_pd(cmd.pd_handle, file->ucontext); 440 + if (!pd) 441 + goto err_release; 624 442 625 443 mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); 626 444 if (IS_ERR(mr)) { 627 445 ret = PTR_ERR(mr); 628 - goto err_up; 446 + goto err_put; 629 447 } 630 448 631 449 mr->device = pd->device; ··· 625 461 atomic_inc(&pd->usecnt); 626 462 atomic_set(&mr->usecnt, 0); 627 463 628 - memset(&resp, 0, sizeof resp); 629 - resp.lkey = mr->lkey; 630 - resp.rkey = mr->rkey; 631 - 632 - ret = idr_add_uobj(&ib_uverbs_mr_idr, mr, &obj->uobject); 464 + obj->uobject.object = mr; 465 + ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject); 633 466 if (ret) 634 467 goto err_unreg; 635 468 469 + memset(&resp, 0, sizeof resp); 470 + resp.lkey = mr->lkey; 471 + resp.rkey = mr->rkey; 636 472 resp.mr_handle = obj->uobject.id; 637 473 638 474 if (copy_to_user((void __user *) (unsigned long) cmd.response, 639 475 &resp, sizeof resp)) { 640 476 ret = -EFAULT; 641 - goto err_idr; 477 + goto err_copy; 642 478 } 479 + 480 + put_pd_read(pd); 643 481 644 482 mutex_lock(&file->mutex); 645 483 list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); 646 484 mutex_unlock(&file->mutex); 647 485 648 - mutex_unlock(&ib_uverbs_idr_mutex); 486 + obj->uobject.live = 1; 487 + 488 + up_write(&obj->uobject.mutex); 649 489 650 490 return in_len; 651 491 652 - err_idr: 653 - idr_remove(&ib_uverbs_mr_idr, obj->uobject.id); 492 + err_copy: 493 + idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject); 654 494 655 495 err_unreg: 656 496 ib_dereg_mr(mr); 657 497 658 - err_up: 659 - mutex_unlock(&ib_uverbs_idr_mutex); 498 + err_put: 499 + put_pd_read(pd); 660 500 501 + err_release: 661 502 ib_umem_release(file->device->ib_dev, &obj->umem); 662 503 663 504 err_free: 664 - kfree(obj); 505 + put_uobj_write(&obj->uobject); 665 506 return ret; 666 507 } 667 508 ··· 676 507 { 677 508 struct ib_uverbs_dereg_mr cmd; 678 509 struct ib_mr *mr; 510 + struct ib_uobject *uobj; 679 511 struct ib_umem_object *memobj; 680 512 int ret = -EINVAL; 681 513 682 514 if (copy_from_user(&cmd, buf, sizeof cmd)) 683 515 return -EFAULT; 684 516 685 - mutex_lock(&ib_uverbs_idr_mutex); 517 + uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext); 518 + if (!uobj) 519 + return -EINVAL; 686 520 687 - mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); 688 - if (!mr || mr->uobject->context != file->ucontext) 689 - goto out; 690 - 691 - memobj = container_of(mr->uobject, struct ib_umem_object, uobject); 521 + memobj = container_of(uobj, struct ib_umem_object, uobject); 522 + mr = uobj->object; 692 523 693 524 ret = ib_dereg_mr(mr); 694 - if (ret) 695 - goto out; 525 + if (!ret) 526 + uobj->live = 0; 696 527 697 - idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); 528 + put_uobj_write(uobj); 529 + 530 + if (ret) 531 + return ret; 532 + 533 + idr_remove_uobj(&ib_uverbs_mr_idr, uobj); 698 534 699 535 mutex_lock(&file->mutex); 700 - list_del(&memobj->uobject.list); 536 + list_del(&uobj->list); 701 537 mutex_unlock(&file->mutex); 702 538 703 539 ib_umem_release(file->device->ib_dev, &memobj->umem); 704 - kfree(memobj); 705 540 706 - out: 707 - mutex_unlock(&ib_uverbs_idr_mutex); 541 + put_uobj(uobj); 708 542 709 - return ret ? ret : in_len; 543 + return in_len; 710 544 } 711 545 712 546 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, ··· 748 576 struct ib_uverbs_create_cq cmd; 749 577 struct ib_uverbs_create_cq_resp resp; 750 578 struct ib_udata udata; 751 - struct ib_ucq_object *uobj; 579 + struct ib_ucq_object *obj; 752 580 struct ib_uverbs_event_file *ev_file = NULL; 753 581 struct ib_cq *cq; 754 582 int ret; ··· 766 594 if (cmd.comp_vector >= file->device->num_comp_vectors) 767 595 return -EINVAL; 768 596 769 - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 770 - if (!uobj) 597 + obj = kmalloc(sizeof *obj, GFP_KERNEL); 598 + if (!obj) 771 599 return -ENOMEM; 600 + 601 + init_uobj(&obj->uobject, cmd.user_handle, file->ucontext); 602 + down_write(&obj->uobject.mutex); 772 603 773 604 if (cmd.comp_channel >= 0) { 774 605 ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); ··· 781 606 } 782 607 } 783 608 784 - uobj->uobject.user_handle = cmd.user_handle; 785 - uobj->uobject.context = file->ucontext; 786 - uobj->uverbs_file = file; 787 - uobj->comp_events_reported = 0; 788 - uobj->async_events_reported = 0; 789 - INIT_LIST_HEAD(&uobj->comp_list); 790 - INIT_LIST_HEAD(&uobj->async_list); 609 + obj->uverbs_file = file; 610 + obj->comp_events_reported = 0; 611 + obj->async_events_reported = 0; 612 + INIT_LIST_HEAD(&obj->comp_list); 613 + INIT_LIST_HEAD(&obj->async_list); 791 614 792 615 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 793 616 file->ucontext, &udata); 794 617 if (IS_ERR(cq)) { 795 618 ret = PTR_ERR(cq); 796 - goto err; 619 + goto err_file; 797 620 } 798 621 799 622 cq->device = file->device->ib_dev; 800 - cq->uobject = &uobj->uobject; 623 + cq->uobject = &obj->uobject; 801 624 cq->comp_handler = ib_uverbs_comp_handler; 802 625 cq->event_handler = ib_uverbs_cq_event_handler; 803 626 cq->cq_context = ev_file; 804 627 atomic_set(&cq->usecnt, 0); 805 628 806 - mutex_lock(&ib_uverbs_idr_mutex); 807 - 808 - ret = idr_add_uobj(&ib_uverbs_cq_idr, cq, &uobj->uobject); 629 + obj->uobject.object = cq; 630 + ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject); 809 631 if (ret) 810 - goto err_up; 632 + goto err_free; 811 633 812 634 memset(&resp, 0, sizeof resp); 813 - resp.cq_handle = uobj->uobject.id; 635 + resp.cq_handle = obj->uobject.id; 814 636 resp.cqe = cq->cqe; 815 637 816 638 if (copy_to_user((void __user *) (unsigned long) cmd.response, 817 639 &resp, sizeof resp)) { 818 640 ret = -EFAULT; 819 - goto err_idr; 641 + goto err_copy; 820 642 } 821 643 822 644 mutex_lock(&file->mutex); 823 - list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); 645 + list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); 824 646 mutex_unlock(&file->mutex); 825 647 826 - mutex_unlock(&ib_uverbs_idr_mutex); 648 + obj->uobject.live = 1; 649 + 650 + up_write(&obj->uobject.mutex); 827 651 828 652 return in_len; 829 653 830 - err_idr: 831 - idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); 654 + err_copy: 655 + idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); 832 656 833 - err_up: 834 - mutex_unlock(&ib_uverbs_idr_mutex); 657 + 658 + err_free: 835 659 ib_destroy_cq(cq); 836 660 837 - err: 661 + err_file: 838 662 if (ev_file) 839 - ib_uverbs_release_ucq(file, ev_file, uobj); 840 - kfree(uobj); 663 + ib_uverbs_release_ucq(file, ev_file, obj); 664 + 665 + err: 666 + put_uobj_write(&obj->uobject); 841 667 return ret; 842 668 } 843 669 ··· 859 683 (unsigned long) cmd.response + sizeof resp, 860 684 in_len - sizeof cmd, out_len - sizeof resp); 861 685 862 - mutex_lock(&ib_uverbs_idr_mutex); 863 - 864 - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 865 - if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq) 866 - goto out; 686 + cq = idr_read_cq(cmd.cq_handle, file->ucontext); 687 + if (!cq) 688 + return -EINVAL; 867 689 868 690 ret = cq->device->resize_cq(cq, cmd.cqe, &udata); 869 691 if (ret) ··· 875 701 ret = -EFAULT; 876 702 877 703 out: 878 - mutex_unlock(&ib_uverbs_idr_mutex); 704 + put_cq_read(cq); 879 705 880 706 return ret ? ret : in_len; 881 707 } ··· 886 712 { 887 713 struct ib_uverbs_poll_cq cmd; 888 714 struct ib_uverbs_poll_cq_resp *resp; 715 + struct ib_uobject *uobj; 889 716 struct ib_cq *cq; 890 717 struct ib_wc *wc; 891 718 int ret = 0; ··· 907 732 goto out_wc; 908 733 } 909 734 910 - mutex_lock(&ib_uverbs_idr_mutex); 911 - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 912 - if (!cq || cq->uobject->context != file->ucontext) { 735 + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 736 + if (!uobj) { 913 737 ret = -EINVAL; 914 738 goto out; 915 739 } 740 + cq = uobj->object; 916 741 917 742 resp->count = ib_poll_cq(cq, cmd.ne, wc); 743 + 744 + put_uobj_read(uobj); 918 745 919 746 for (i = 0; i < resp->count; i++) { 920 747 resp->wc[i].wr_id = wc[i].wr_id; ··· 939 762 ret = -EFAULT; 940 763 941 764 out: 942 - mutex_unlock(&ib_uverbs_idr_mutex); 943 765 kfree(resp); 944 766 945 767 out_wc: ··· 951 775 int out_len) 952 776 { 953 777 struct ib_uverbs_req_notify_cq cmd; 778 + struct ib_uobject *uobj; 954 779 struct ib_cq *cq; 955 - int ret = -EINVAL; 956 780 957 781 if (copy_from_user(&cmd, buf, sizeof cmd)) 958 782 return -EFAULT; 959 783 960 - mutex_lock(&ib_uverbs_idr_mutex); 961 - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 962 - if (cq && cq->uobject->context == file->ucontext) { 963 - ib_req_notify_cq(cq, cmd.solicited_only ? 964 - IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 965 - ret = in_len; 966 - } 967 - mutex_unlock(&ib_uverbs_idr_mutex); 784 + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 785 + if (!uobj) 786 + return -EINVAL; 787 + cq = uobj->object; 968 788 969 - return ret; 789 + ib_req_notify_cq(cq, cmd.solicited_only ? 790 + IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 791 + 792 + put_uobj_read(uobj); 793 + 794 + return in_len; 970 795 } 971 796 972 797 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, ··· 976 799 { 977 800 struct ib_uverbs_destroy_cq cmd; 978 801 struct ib_uverbs_destroy_cq_resp resp; 802 + struct ib_uobject *uobj; 979 803 struct ib_cq *cq; 980 - struct ib_ucq_object *uobj; 804 + struct ib_ucq_object *obj; 981 805 struct ib_uverbs_event_file *ev_file; 982 - u64 user_handle; 983 806 int ret = -EINVAL; 984 807 985 808 if (copy_from_user(&cmd, buf, sizeof cmd)) 986 809 return -EFAULT; 987 810 988 - memset(&resp, 0, sizeof resp); 989 - 990 - mutex_lock(&ib_uverbs_idr_mutex); 991 - 992 - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 993 - if (!cq || cq->uobject->context != file->ucontext) 994 - goto out; 995 - 996 - user_handle = cq->uobject->user_handle; 997 - uobj = container_of(cq->uobject, struct ib_ucq_object, uobject); 998 - ev_file = cq->cq_context; 811 + uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 812 + if (!uobj) 813 + return -EINVAL; 814 + cq = uobj->object; 815 + ev_file = cq->cq_context; 816 + obj = container_of(cq->uobject, struct ib_ucq_object, uobject); 999 817 1000 818 ret = ib_destroy_cq(cq); 1001 - if (ret) 1002 - goto out; 819 + if (!ret) 820 + uobj->live = 0; 1003 821 1004 - idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 822 + put_uobj_write(uobj); 823 + 824 + if (ret) 825 + return ret; 826 + 827 + idr_remove_uobj(&ib_uverbs_cq_idr, uobj); 1005 828 1006 829 mutex_lock(&file->mutex); 1007 - list_del(&uobj->uobject.list); 830 + list_del(&uobj->list); 1008 831 mutex_unlock(&file->mutex); 1009 832 1010 - ib_uverbs_release_ucq(file, ev_file, uobj); 833 + ib_uverbs_release_ucq(file, ev_file, obj); 1011 834 1012 - resp.comp_events_reported = uobj->comp_events_reported; 1013 - resp.async_events_reported = uobj->async_events_reported; 835 + memset(&resp, 0, sizeof resp); 836 + resp.comp_events_reported = obj->comp_events_reported; 837 + resp.async_events_reported = obj->async_events_reported; 1014 838 1015 - kfree(uobj); 839 + put_uobj(uobj); 1016 840 1017 841 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1018 842 &resp, sizeof resp)) 1019 - ret = -EFAULT; 843 + return -EFAULT; 1020 844 1021 - out: 1022 - mutex_unlock(&ib_uverbs_idr_mutex); 1023 - 1024 - return ret ? ret : in_len; 845 + return in_len; 1025 846 } 1026 847 1027 848 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, ··· 1029 854 struct ib_uverbs_create_qp cmd; 1030 855 struct ib_uverbs_create_qp_resp resp; 1031 856 struct ib_udata udata; 1032 - struct ib_uqp_object *uobj; 857 + struct ib_uqp_object *obj; 1033 858 struct ib_pd *pd; 1034 859 struct ib_cq *scq, *rcq; 1035 860 struct ib_srq *srq; ··· 1047 872 (unsigned long) cmd.response + sizeof resp, 1048 873 in_len - sizeof cmd, out_len - sizeof resp); 1049 874 1050 - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 1051 - if (!uobj) 875 + obj = kmalloc(sizeof *obj, GFP_KERNEL); 876 + if (!obj) 1052 877 return -ENOMEM; 1053 878 1054 - mutex_lock(&ib_uverbs_idr_mutex); 879 + init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext); 880 + down_write(&obj->uevent.uobject.mutex); 1055 881 1056 - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1057 - scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 1058 - rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); 1059 - srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL; 882 + pd = idr_read_pd(cmd.pd_handle, file->ucontext); 883 + scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); 884 + rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext); 885 + srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; 1060 886 1061 - if (!pd || pd->uobject->context != file->ucontext || 1062 - !scq || scq->uobject->context != file->ucontext || 1063 - !rcq || rcq->uobject->context != file->ucontext || 1064 - (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) { 887 + if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { 1065 888 ret = -EINVAL; 1066 - goto err_up; 889 + goto err_put; 1067 890 } 1068 891 1069 892 attr.event_handler = ib_uverbs_qp_event_handler; ··· 1078 905 attr.cap.max_recv_sge = cmd.max_recv_sge; 1079 906 attr.cap.max_inline_data = cmd.max_inline_data; 1080 907 1081 - uobj->uevent.uobject.user_handle = cmd.user_handle; 1082 - uobj->uevent.uobject.context = file->ucontext; 1083 - uobj->uevent.events_reported = 0; 1084 - INIT_LIST_HEAD(&uobj->uevent.event_list); 1085 - INIT_LIST_HEAD(&uobj->mcast_list); 908 + obj->uevent.events_reported = 0; 909 + INIT_LIST_HEAD(&obj->uevent.event_list); 910 + INIT_LIST_HEAD(&obj->mcast_list); 1086 911 1087 912 qp = pd->device->create_qp(pd, &attr, &udata); 1088 913 if (IS_ERR(qp)) { 1089 914 ret = PTR_ERR(qp); 1090 - goto err_up; 915 + goto err_put; 1091 916 } 1092 917 1093 918 qp->device = pd->device; ··· 1093 922 qp->send_cq = attr.send_cq; 1094 923 qp->recv_cq = attr.recv_cq; 1095 924 qp->srq = attr.srq; 1096 - qp->uobject = &uobj->uevent.uobject; 925 + qp->uobject = &obj->uevent.uobject; 1097 926 qp->event_handler = attr.event_handler; 1098 927 qp->qp_context = attr.qp_context; 1099 928 qp->qp_type = attr.qp_type; ··· 1103 932 if (attr.srq) 1104 933 atomic_inc(&attr.srq->usecnt); 1105 934 1106 - memset(&resp, 0, sizeof resp); 1107 - resp.qpn = qp->qp_num; 1108 - 1109 - ret = idr_add_uobj(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject); 935 + obj->uevent.uobject.object = qp; 936 + ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1110 937 if (ret) 1111 938 goto err_destroy; 1112 939 1113 - resp.qp_handle = uobj->uevent.uobject.id; 940 + memset(&resp, 0, sizeof resp); 941 + resp.qpn = qp->qp_num; 942 + resp.qp_handle = obj->uevent.uobject.id; 1114 943 resp.max_recv_sge = attr.cap.max_recv_sge; 1115 944 resp.max_send_sge = attr.cap.max_send_sge; 1116 945 resp.max_recv_wr = attr.cap.max_recv_wr; ··· 1120 949 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1121 950 &resp, sizeof resp)) { 1122 951 ret = -EFAULT; 1123 - goto err_idr; 952 + goto err_copy; 1124 953 } 1125 954 955 + put_pd_read(pd); 956 + put_cq_read(scq); 957 + put_cq_read(rcq); 958 + if (srq) 959 + put_srq_read(srq); 960 + 1126 961 mutex_lock(&file->mutex); 1127 - list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); 962 + list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list); 1128 963 mutex_unlock(&file->mutex); 1129 964 1130 - mutex_unlock(&ib_uverbs_idr_mutex); 965 + obj->uevent.uobject.live = 1; 966 + 967 + up_write(&obj->uevent.uobject.mutex); 1131 968 1132 969 return in_len; 1133 970 1134 - err_idr: 1135 - idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id); 971 + err_copy: 972 + idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1136 973 1137 974 err_destroy: 1138 975 ib_destroy_qp(qp); 1139 976 1140 - err_up: 1141 - mutex_unlock(&ib_uverbs_idr_mutex); 977 + err_put: 978 + if (pd) 979 + put_pd_read(pd); 980 + if (scq) 981 + put_cq_read(scq); 982 + if (rcq) 983 + put_cq_read(rcq); 984 + if (srq) 985 + put_srq_read(srq); 1142 986 1143 - kfree(uobj); 987 + put_uobj_write(&obj->uevent.uobject); 1144 988 return ret; 1145 989 } 1146 990 ··· 1180 994 goto out; 1181 995 } 1182 996 1183 - mutex_lock(&ib_uverbs_idr_mutex); 1184 - 1185 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1186 - if (qp && qp->uobject->context == file->ucontext) 1187 - ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); 1188 - else 997 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 998 + if (!qp) { 1189 999 ret = -EINVAL; 1000 + goto out; 1001 + } 1190 1002 1191 - mutex_unlock(&ib_uverbs_idr_mutex); 1003 + ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); 1004 + 1005 + put_qp_read(qp); 1192 1006 1193 1007 if (ret) 1194 1008 goto out; ··· 1275 1089 if (!attr) 1276 1090 return -ENOMEM; 1277 1091 1278 - mutex_lock(&ib_uverbs_idr_mutex); 1279 - 1280 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1281 - if (!qp || qp->uobject->context != file->ucontext) { 1092 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1093 + if (!qp) { 1282 1094 ret = -EINVAL; 1283 1095 goto out; 1284 1096 } ··· 1328 1144 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 1329 1145 1330 1146 ret = ib_modify_qp(qp, attr, cmd.attr_mask); 1147 + 1148 + put_qp_read(qp); 1149 + 1331 1150 if (ret) 1332 1151 goto out; 1333 1152 1334 1153 ret = in_len; 1335 1154 1336 1155 out: 1337 - mutex_unlock(&ib_uverbs_idr_mutex); 1338 1156 kfree(attr); 1339 1157 1340 1158 return ret; ··· 1348 1162 { 1349 1163 struct ib_uverbs_destroy_qp cmd; 1350 1164 struct ib_uverbs_destroy_qp_resp resp; 1165 + struct ib_uobject *uobj; 1351 1166 struct ib_qp *qp; 1352 - struct ib_uqp_object *uobj; 1167 + struct ib_uqp_object *obj; 1353 1168 int ret = -EINVAL; 1354 1169 1355 1170 if (copy_from_user(&cmd, buf, sizeof cmd)) ··· 1358 1171 1359 1172 memset(&resp, 0, sizeof resp); 1360 1173 1361 - mutex_lock(&ib_uverbs_idr_mutex); 1174 + uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext); 1175 + if (!uobj) 1176 + return -EINVAL; 1177 + qp = uobj->object; 1178 + obj = container_of(uobj, struct ib_uqp_object, uevent.uobject); 1362 1179 1363 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1364 - if (!qp || qp->uobject->context != file->ucontext) 1365 - goto out; 1366 - 1367 - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1368 - 1369 - if (!list_empty(&uobj->mcast_list)) { 1370 - ret = -EBUSY; 1371 - goto out; 1180 + if (!list_empty(&obj->mcast_list)) { 1181 + put_uobj_write(uobj); 1182 + return -EBUSY; 1372 1183 } 1373 1184 1374 1185 ret = ib_destroy_qp(qp); 1375 - if (ret) 1376 - goto out; 1186 + if (!ret) 1187 + uobj->live = 0; 1377 1188 1378 - idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 1189 + put_uobj_write(uobj); 1190 + 1191 + if (ret) 1192 + return ret; 1193 + 1194 + idr_remove_uobj(&ib_uverbs_qp_idr, uobj); 1379 1195 1380 1196 mutex_lock(&file->mutex); 1381 - list_del(&uobj->uevent.uobject.list); 1197 + list_del(&uobj->list); 1382 1198 mutex_unlock(&file->mutex); 1383 1199 1384 - ib_uverbs_release_uevent(file, &uobj->uevent); 1200 + ib_uverbs_release_uevent(file, &obj->uevent); 1385 1201 1386 - resp.events_reported = uobj->uevent.events_reported; 1202 + resp.events_reported = obj->uevent.events_reported; 1387 1203 1388 - kfree(uobj); 1204 + put_uobj(uobj); 1389 1205 1390 1206 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1391 1207 &resp, sizeof resp)) 1392 - ret = -EFAULT; 1208 + return -EFAULT; 1393 1209 1394 - out: 1395 - mutex_unlock(&ib_uverbs_idr_mutex); 1396 - 1397 - return ret ? ret : in_len; 1210 + return in_len; 1398 1211 } 1399 1212 1400 1213 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, ··· 1407 1220 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr; 1408 1221 struct ib_qp *qp; 1409 1222 int i, sg_ind; 1223 + int is_ud; 1410 1224 ssize_t ret = -EINVAL; 1411 1225 1412 1226 if (copy_from_user(&cmd, buf, sizeof cmd)) ··· 1424 1236 if (!user_wr) 1425 1237 return -ENOMEM; 1426 1238 1427 - mutex_lock(&ib_uverbs_idr_mutex); 1428 - 1429 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1430 - if (!qp || qp->uobject->context != file->ucontext) 1239 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1240 + if (!qp) 1431 1241 goto out; 1432 1242 1243 + is_ud = qp->qp_type == IB_QPT_UD; 1433 1244 sg_ind = 0; 1434 1245 last = NULL; 1435 1246 for (i = 0; i < cmd.wr_count; ++i) { ··· 1436 1249 buf + sizeof cmd + i * cmd.wqe_size, 1437 1250 cmd.wqe_size)) { 1438 1251 ret = -EFAULT; 1439 - goto out; 1252 + goto out_put; 1440 1253 } 1441 1254 1442 1255 if (user_wr->num_sge + sg_ind > cmd.sge_count) { 1443 1256 ret = -EINVAL; 1444 - goto out; 1257 + goto out_put; 1445 1258 } 1446 1259 1447 1260 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + ··· 1449 1262 GFP_KERNEL); 1450 1263 if (!next) { 1451 1264 ret = -ENOMEM; 1452 - goto out; 1265 + goto out_put; 1453 1266 } 1454 1267 1455 1268 if (!last) ··· 1465 1278 next->send_flags = user_wr->send_flags; 1466 1279 next->imm_data = (__be32 __force) user_wr->imm_data; 1467 1280 1468 - if (qp->qp_type == IB_QPT_UD) { 1469 - next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, 1470 - user_wr->wr.ud.ah); 1281 + if (is_ud) { 1282 + next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah, 1283 + file->ucontext); 1471 1284 if (!next->wr.ud.ah) { 1472 1285 ret = -EINVAL; 1473 - goto out; 1286 + goto out_put; 1474 1287 } 1475 1288 next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn; 1476 1289 next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey; ··· 1507 1320 sg_ind * sizeof (struct ib_sge), 1508 1321 next->num_sge * sizeof (struct ib_sge))) { 1509 1322 ret = -EFAULT; 1510 - goto out; 1323 + goto out_put; 1511 1324 } 1512 1325 sg_ind += next->num_sge; 1513 1326 } else ··· 1527 1340 &resp, sizeof resp)) 1528 1341 ret = -EFAULT; 1529 1342 1530 - out: 1531 - mutex_unlock(&ib_uverbs_idr_mutex); 1343 + out_put: 1344 + put_qp_read(qp); 1532 1345 1346 + out: 1533 1347 while (wr) { 1348 + if (is_ud && wr->wr.ud.ah) 1349 + put_ah_read(wr->wr.ud.ah); 1534 1350 next = wr->next; 1535 1351 kfree(wr); 1536 1352 wr = next; ··· 1648 1458 if (IS_ERR(wr)) 1649 1459 return PTR_ERR(wr); 1650 1460 1651 - mutex_lock(&ib_uverbs_idr_mutex); 1652 - 1653 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1654 - if (!qp || qp->uobject->context != file->ucontext) 1461 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1462 + if (!qp) 1655 1463 goto out; 1656 1464 1657 1465 resp.bad_wr = 0; 1658 1466 ret = qp->device->post_recv(qp, wr, &bad_wr); 1467 + 1468 + put_qp_read(qp); 1469 + 1659 1470 if (ret) 1660 1471 for (next = wr; next; next = next->next) { 1661 1472 ++resp.bad_wr; ··· 1670 1479 ret = -EFAULT; 1671 1480 1672 1481 out: 1673 - mutex_unlock(&ib_uverbs_idr_mutex); 1674 - 1675 1482 while (wr) { 1676 1483 next = wr->next; 1677 1484 kfree(wr); ··· 1698 1509 if (IS_ERR(wr)) 1699 1510 return PTR_ERR(wr); 1700 1511 1701 - mutex_lock(&ib_uverbs_idr_mutex); 1702 - 1703 - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1704 - if (!srq || srq->uobject->context != file->ucontext) 1512 + srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1513 + if (!srq) 1705 1514 goto out; 1706 1515 1707 1516 resp.bad_wr = 0; 1708 1517 ret = srq->device->post_srq_recv(srq, wr, &bad_wr); 1518 + 1519 + put_srq_read(srq); 1520 + 1709 1521 if (ret) 1710 1522 for (next = wr; next; next = next->next) { 1711 1523 ++resp.bad_wr; ··· 1720 1530 ret = -EFAULT; 1721 1531 1722 1532 out: 1723 - mutex_unlock(&ib_uverbs_idr_mutex); 1724 - 1725 1533 while (wr) { 1726 1534 next = wr->next; 1727 1535 kfree(wr); ··· 1751 1563 if (!uobj) 1752 1564 return -ENOMEM; 1753 1565 1754 - mutex_lock(&ib_uverbs_idr_mutex); 1566 + init_uobj(uobj, cmd.user_handle, file->ucontext); 1567 + down_write(&uobj->mutex); 1755 1568 1756 - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1757 - if (!pd || pd->uobject->context != file->ucontext) { 1569 + pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1570 + if (!pd) { 1758 1571 ret = -EINVAL; 1759 - goto err_up; 1572 + goto err; 1760 1573 } 1761 - 1762 - uobj->user_handle = cmd.user_handle; 1763 - uobj->context = file->ucontext; 1764 1574 1765 1575 attr.dlid = cmd.attr.dlid; 1766 1576 attr.sl = cmd.attr.sl; ··· 1775 1589 ah = ib_create_ah(pd, &attr); 1776 1590 if (IS_ERR(ah)) { 1777 1591 ret = PTR_ERR(ah); 1778 - goto err_up; 1592 + goto err; 1779 1593 } 1780 1594 1781 - ah->uobject = uobj; 1595 + ah->uobject = uobj; 1596 + uobj->object = ah; 1782 1597 1783 - ret = idr_add_uobj(&ib_uverbs_ah_idr, ah, uobj); 1598 + ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj); 1784 1599 if (ret) 1785 1600 goto err_destroy; 1786 1601 ··· 1790 1603 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1791 1604 &resp, sizeof resp)) { 1792 1605 ret = -EFAULT; 1793 - goto err_idr; 1606 + goto err_copy; 1794 1607 } 1608 + 1609 + put_pd_read(pd); 1795 1610 1796 1611 mutex_lock(&file->mutex); 1797 1612 list_add_tail(&uobj->list, &file->ucontext->ah_list); 1798 1613 mutex_unlock(&file->mutex); 1799 1614 1800 - mutex_unlock(&ib_uverbs_idr_mutex); 1615 + uobj->live = 1; 1616 + 1617 + up_write(&uobj->mutex); 1801 1618 1802 1619 return in_len; 1803 1620 1804 - err_idr: 1805 - idr_remove(&ib_uverbs_ah_idr, uobj->id); 1621 + err_copy: 1622 + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); 1806 1623 1807 1624 err_destroy: 1808 1625 ib_destroy_ah(ah); 1809 1626 1810 - err_up: 1811 - mutex_unlock(&ib_uverbs_idr_mutex); 1812 - 1813 - kfree(uobj); 1627 + err: 1628 + put_uobj_write(uobj); 1814 1629 return ret; 1815 1630 } 1816 1631 ··· 1822 1633 struct ib_uverbs_destroy_ah cmd; 1823 1634 struct ib_ah *ah; 1824 1635 struct ib_uobject *uobj; 1825 - int ret = -EINVAL; 1636 + int ret; 1826 1637 1827 1638 if (copy_from_user(&cmd, buf, sizeof cmd)) 1828 1639 return -EFAULT; 1829 1640 1830 - mutex_lock(&ib_uverbs_idr_mutex); 1831 - 1832 - ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); 1833 - if (!ah || ah->uobject->context != file->ucontext) 1834 - goto out; 1835 - 1836 - uobj = ah->uobject; 1641 + uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext); 1642 + if (!uobj) 1643 + return -EINVAL; 1644 + ah = uobj->object; 1837 1645 1838 1646 ret = ib_destroy_ah(ah); 1839 - if (ret) 1840 - goto out; 1647 + if (!ret) 1648 + uobj->live = 0; 1841 1649 1842 - idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); 1650 + put_uobj_write(uobj); 1651 + 1652 + if (ret) 1653 + return ret; 1654 + 1655 + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); 1843 1656 1844 1657 mutex_lock(&file->mutex); 1845 1658 list_del(&uobj->list); 1846 1659 mutex_unlock(&file->mutex); 1847 1660 1848 - kfree(uobj); 1661 + put_uobj(uobj); 1849 1662 1850 - out: 1851 - mutex_unlock(&ib_uverbs_idr_mutex); 1852 - 1853 - return ret ? ret : in_len; 1663 + return in_len; 1854 1664 } 1855 1665 1856 1666 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, ··· 1858 1670 { 1859 1671 struct ib_uverbs_attach_mcast cmd; 1860 1672 struct ib_qp *qp; 1861 - struct ib_uqp_object *uobj; 1673 + struct ib_uqp_object *obj; 1862 1674 struct ib_uverbs_mcast_entry *mcast; 1863 - int ret = -EINVAL; 1675 + int ret; 1864 1676 1865 1677 if (copy_from_user(&cmd, buf, sizeof cmd)) 1866 1678 return -EFAULT; 1867 1679 1868 - mutex_lock(&ib_uverbs_idr_mutex); 1680 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1681 + if (!qp) 1682 + return -EINVAL; 1869 1683 1870 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1871 - if (!qp || qp->uobject->context != file->ucontext) 1872 - goto out; 1684 + obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1873 1685 1874 - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1875 - 1876 - list_for_each_entry(mcast, &uobj->mcast_list, list) 1686 + list_for_each_entry(mcast, &obj->mcast_list, list) 1877 1687 if (cmd.mlid == mcast->lid && 1878 1688 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 1879 1689 ret = 0; 1880 - goto out; 1690 + goto out_put; 1881 1691 } 1882 1692 1883 1693 mcast = kmalloc(sizeof *mcast, GFP_KERNEL); 1884 1694 if (!mcast) { 1885 1695 ret = -ENOMEM; 1886 - goto out; 1696 + goto out_put; 1887 1697 } 1888 1698 1889 1699 mcast->lid = cmd.mlid; 1890 1700 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw); 1891 1701 1892 1702 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid); 1893 - if (!ret) { 1894 - uobj = container_of(qp->uobject, struct ib_uqp_object, 1895 - uevent.uobject); 1896 - list_add_tail(&mcast->list, &uobj->mcast_list); 1897 - } else 1703 + if (!ret) 1704 + list_add_tail(&mcast->list, &obj->mcast_list); 1705 + else 1898 1706 kfree(mcast); 1899 1707 1900 - out: 1901 - mutex_unlock(&ib_uverbs_idr_mutex); 1708 + out_put: 1709 + put_qp_read(qp); 1902 1710 1903 1711 return ret ? ret : in_len; 1904 1712 } ··· 1904 1720 int out_len) 1905 1721 { 1906 1722 struct ib_uverbs_detach_mcast cmd; 1907 - struct ib_uqp_object *uobj; 1723 + struct ib_uqp_object *obj; 1908 1724 struct ib_qp *qp; 1909 1725 struct ib_uverbs_mcast_entry *mcast; 1910 1726 int ret = -EINVAL; ··· 1912 1728 if (copy_from_user(&cmd, buf, sizeof cmd)) 1913 1729 return -EFAULT; 1914 1730 1915 - mutex_lock(&ib_uverbs_idr_mutex); 1916 - 1917 - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1918 - if (!qp || qp->uobject->context != file->ucontext) 1919 - goto out; 1731 + qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1732 + if (!qp) 1733 + return -EINVAL; 1920 1734 1921 1735 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1922 1736 if (ret) 1923 - goto out; 1737 + goto out_put; 1924 1738 1925 - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1739 + obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1926 1740 1927 - list_for_each_entry(mcast, &uobj->mcast_list, list) 1741 + list_for_each_entry(mcast, &obj->mcast_list, list) 1928 1742 if (cmd.mlid == mcast->lid && 1929 1743 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 1930 1744 list_del(&mcast->list); ··· 1930 1748 break; 1931 1749 } 1932 1750 1933 - out: 1934 - mutex_unlock(&ib_uverbs_idr_mutex); 1751 + out_put: 1752 + put_qp_read(qp); 1935 1753 1936 1754 return ret ? ret : in_len; 1937 1755 } ··· 1943 1761 struct ib_uverbs_create_srq cmd; 1944 1762 struct ib_uverbs_create_srq_resp resp; 1945 1763 struct ib_udata udata; 1946 - struct ib_uevent_object *uobj; 1764 + struct ib_uevent_object *obj; 1947 1765 struct ib_pd *pd; 1948 1766 struct ib_srq *srq; 1949 1767 struct ib_srq_init_attr attr; ··· 1959 1777 (unsigned long) cmd.response + sizeof resp, 1960 1778 in_len - sizeof cmd, out_len - sizeof resp); 1961 1779 1962 - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 1963 - if (!uobj) 1780 + obj = kmalloc(sizeof *obj, GFP_KERNEL); 1781 + if (!obj) 1964 1782 return -ENOMEM; 1965 1783 1966 - mutex_lock(&ib_uverbs_idr_mutex); 1784 + init_uobj(&obj->uobject, 0, file->ucontext); 1785 + down_write(&obj->uobject.mutex); 1967 1786 1968 - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1969 - 1970 - if (!pd || pd->uobject->context != file->ucontext) { 1787 + pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1788 + if (!pd) { 1971 1789 ret = -EINVAL; 1972 - goto err_up; 1790 + goto err; 1973 1791 } 1974 1792 1975 1793 attr.event_handler = ib_uverbs_srq_event_handler; ··· 1978 1796 attr.attr.max_sge = cmd.max_sge; 1979 1797 attr.attr.srq_limit = cmd.srq_limit; 1980 1798 1981 - uobj->uobject.user_handle = cmd.user_handle; 1982 - uobj->uobject.context = file->ucontext; 1983 - uobj->events_reported = 0; 1984 - INIT_LIST_HEAD(&uobj->event_list); 1799 + obj->events_reported = 0; 1800 + INIT_LIST_HEAD(&obj->event_list); 1985 1801 1986 1802 srq = pd->device->create_srq(pd, &attr, &udata); 1987 1803 if (IS_ERR(srq)) { 1988 1804 ret = PTR_ERR(srq); 1989 - goto err_up; 1805 + goto err; 1990 1806 } 1991 1807 1992 1808 srq->device = pd->device; 1993 1809 srq->pd = pd; 1994 - srq->uobject = &uobj->uobject; 1810 + srq->uobject = &obj->uobject; 1995 1811 srq->event_handler = attr.event_handler; 1996 1812 srq->srq_context = attr.srq_context; 1997 1813 atomic_inc(&pd->usecnt); 1998 1814 atomic_set(&srq->usecnt, 0); 1999 1815 2000 - memset(&resp, 0, sizeof resp); 2001 - 2002 - ret = idr_add_uobj(&ib_uverbs_srq_idr, srq, &uobj->uobject); 1816 + obj->uobject.object = srq; 1817 + ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject); 2003 1818 if (ret) 2004 1819 goto err_destroy; 2005 1820 2006 - resp.srq_handle = uobj->uobject.id; 1821 + memset(&resp, 0, sizeof resp); 1822 + resp.srq_handle = obj->uobject.id; 2007 1823 resp.max_wr = attr.attr.max_wr; 2008 1824 resp.max_sge = attr.attr.max_sge; 2009 1825 2010 1826 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2011 1827 &resp, sizeof resp)) { 2012 1828 ret = -EFAULT; 2013 - goto err_idr; 1829 + goto err_copy; 2014 1830 } 2015 1831 1832 + put_pd_read(pd); 1833 + 2016 1834 mutex_lock(&file->mutex); 2017 - list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); 1835 + list_add_tail(&obj->uobject.list, &file->ucontext->srq_list); 2018 1836 mutex_unlock(&file->mutex); 2019 1837 2020 - mutex_unlock(&ib_uverbs_idr_mutex); 1838 + obj->uobject.live = 1; 1839 + 1840 + up_write(&obj->uobject.mutex); 2021 1841 2022 1842 return in_len; 2023 1843 2024 - err_idr: 2025 - idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id); 1844 + err_copy: 1845 + idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject); 2026 1846 2027 1847 err_destroy: 2028 1848 ib_destroy_srq(srq); 2029 1849 2030 - err_up: 2031 - mutex_unlock(&ib_uverbs_idr_mutex); 2032 - 2033 - kfree(uobj); 1850 + err: 1851 + put_uobj_write(&obj->uobject); 2034 1852 return ret; 2035 1853 } 2036 1854 ··· 2046 1864 if (copy_from_user(&cmd, buf, sizeof cmd)) 2047 1865 return -EFAULT; 2048 1866 2049 - mutex_lock(&ib_uverbs_idr_mutex); 2050 - 2051 - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 2052 - if (!srq || srq->uobject->context != file->ucontext) { 2053 - ret = -EINVAL; 2054 - goto out; 2055 - } 1867 + srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1868 + if (!srq) 1869 + return -EINVAL; 2056 1870 2057 1871 attr.max_wr = cmd.max_wr; 2058 1872 attr.srq_limit = cmd.srq_limit; 2059 1873 2060 1874 ret = ib_modify_srq(srq, &attr, cmd.attr_mask); 2061 1875 2062 - out: 2063 - mutex_unlock(&ib_uverbs_idr_mutex); 1876 + put_srq_read(srq); 2064 1877 2065 1878 return ret ? ret : in_len; 2066 1879 } ··· 2076 1899 if (copy_from_user(&cmd, buf, sizeof cmd)) 2077 1900 return -EFAULT; 2078 1901 2079 - mutex_lock(&ib_uverbs_idr_mutex); 1902 + srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1903 + if (!srq) 1904 + return -EINVAL; 2080 1905 2081 - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 2082 - if (srq && srq->uobject->context == file->ucontext) 2083 - ret = ib_query_srq(srq, &attr); 2084 - else 2085 - ret = -EINVAL; 1906 + ret = ib_query_srq(srq, &attr); 2086 1907 2087 - mutex_unlock(&ib_uverbs_idr_mutex); 1908 + put_srq_read(srq); 2088 1909 2089 1910 if (ret) 2090 - goto out; 1911 + return ret; 2091 1912 2092 1913 memset(&resp, 0, sizeof resp); 2093 1914 ··· 2095 1920 2096 1921 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2097 1922 &resp, sizeof resp)) 2098 - ret = -EFAULT; 1923 + return -EFAULT; 2099 1924 2100 - out: 2101 - return ret ? ret : in_len; 1925 + return in_len; 2102 1926 } 2103 1927 2104 1928 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, ··· 2106 1932 { 2107 1933 struct ib_uverbs_destroy_srq cmd; 2108 1934 struct ib_uverbs_destroy_srq_resp resp; 1935 + struct ib_uobject *uobj; 2109 1936 struct ib_srq *srq; 2110 - struct ib_uevent_object *uobj; 1937 + struct ib_uevent_object *obj; 2111 1938 int ret = -EINVAL; 2112 1939 2113 1940 if (copy_from_user(&cmd, buf, sizeof cmd)) 2114 1941 return -EFAULT; 2115 1942 2116 - mutex_lock(&ib_uverbs_idr_mutex); 2117 - 2118 - memset(&resp, 0, sizeof resp); 2119 - 2120 - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 2121 - if (!srq || srq->uobject->context != file->ucontext) 2122 - goto out; 2123 - 2124 - uobj = container_of(srq->uobject, struct ib_uevent_object, uobject); 1943 + uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext); 1944 + if (!uobj) 1945 + return -EINVAL; 1946 + srq = uobj->object; 1947 + obj = container_of(uobj, struct ib_uevent_object, uobject); 2125 1948 2126 1949 ret = ib_destroy_srq(srq); 2127 - if (ret) 2128 - goto out; 1950 + if (!ret) 1951 + uobj->live = 0; 2129 1952 2130 - idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1953 + put_uobj_write(uobj); 1954 + 1955 + if (ret) 1956 + return ret; 1957 + 1958 + idr_remove_uobj(&ib_uverbs_srq_idr, uobj); 2131 1959 2132 1960 mutex_lock(&file->mutex); 2133 - list_del(&uobj->uobject.list); 1961 + list_del(&uobj->list); 2134 1962 mutex_unlock(&file->mutex); 2135 1963 2136 - ib_uverbs_release_uevent(file, uobj); 1964 + ib_uverbs_release_uevent(file, obj); 2137 1965 2138 - resp.events_reported = uobj->events_reported; 1966 + memset(&resp, 0, sizeof resp); 1967 + resp.events_reported = obj->events_reported; 2139 1968 2140 - kfree(uobj); 1969 + put_uobj(uobj); 2141 1970 2142 1971 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2143 1972 &resp, sizeof resp)) 2144 1973 ret = -EFAULT; 2145 - 2146 - out: 2147 - mutex_unlock(&ib_uverbs_idr_mutex); 2148 1974 2149 1975 return ret ? ret : in_len; 2150 1976 }
+18 -17
drivers/infiniband/core/uverbs_main.c
··· 66 66 67 67 static struct class *uverbs_class; 68 68 69 - DEFINE_MUTEX(ib_uverbs_idr_mutex); 69 + DEFINE_SPINLOCK(ib_uverbs_idr_lock); 70 70 DEFINE_IDR(ib_uverbs_pd_idr); 71 71 DEFINE_IDR(ib_uverbs_mr_idr); 72 72 DEFINE_IDR(ib_uverbs_mw_idr); ··· 183 183 if (!context) 184 184 return 0; 185 185 186 - mutex_lock(&ib_uverbs_idr_mutex); 187 - 188 186 list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { 189 - struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); 190 - idr_remove(&ib_uverbs_ah_idr, uobj->id); 187 + struct ib_ah *ah = uobj->object; 188 + 189 + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); 191 190 ib_destroy_ah(ah); 192 191 list_del(&uobj->list); 193 192 kfree(uobj); 194 193 } 195 194 196 195 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { 197 - struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id); 196 + struct ib_qp *qp = uobj->object; 198 197 struct ib_uqp_object *uqp = 199 198 container_of(uobj, struct ib_uqp_object, uevent.uobject); 200 - idr_remove(&ib_uverbs_qp_idr, uobj->id); 199 + 200 + idr_remove_uobj(&ib_uverbs_qp_idr, uobj); 201 201 ib_uverbs_detach_umcast(qp, uqp); 202 202 ib_destroy_qp(qp); 203 203 list_del(&uobj->list); ··· 206 206 } 207 207 208 208 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 209 - struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id); 209 + struct ib_cq *cq = uobj->object; 210 210 struct ib_uverbs_event_file *ev_file = cq->cq_context; 211 211 struct ib_ucq_object *ucq = 212 212 container_of(uobj, struct ib_ucq_object, uobject); 213 - idr_remove(&ib_uverbs_cq_idr, uobj->id); 213 + 214 + idr_remove_uobj(&ib_uverbs_cq_idr, uobj); 214 215 ib_destroy_cq(cq); 215 216 list_del(&uobj->list); 216 217 ib_uverbs_release_ucq(file, ev_file, ucq); ··· 219 218 } 220 219 221 220 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 222 - struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id); 221 + struct ib_srq *srq = uobj->object; 223 222 struct ib_uevent_object *uevent = 224 223 container_of(uobj, struct ib_uevent_object, uobject); 225 - idr_remove(&ib_uverbs_srq_idr, uobj->id); 224 + 225 + idr_remove_uobj(&ib_uverbs_srq_idr, uobj); 226 226 ib_destroy_srq(srq); 227 227 list_del(&uobj->list); 228 228 ib_uverbs_release_uevent(file, uevent); ··· 233 231 /* XXX Free MWs */ 234 232 235 233 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { 236 - struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id); 234 + struct ib_mr *mr = uobj->object; 237 235 struct ib_device *mrdev = mr->device; 238 236 struct ib_umem_object *memobj; 239 237 240 - idr_remove(&ib_uverbs_mr_idr, uobj->id); 238 + idr_remove_uobj(&ib_uverbs_mr_idr, uobj); 241 239 ib_dereg_mr(mr); 242 240 243 241 memobj = container_of(uobj, struct ib_umem_object, uobject); ··· 248 246 } 249 247 250 248 list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { 251 - struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id); 252 - idr_remove(&ib_uverbs_pd_idr, uobj->id); 249 + struct ib_pd *pd = uobj->object; 250 + 251 + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); 253 252 ib_dealloc_pd(pd); 254 253 list_del(&uobj->list); 255 254 kfree(uobj); 256 255 } 257 - 258 - mutex_unlock(&ib_uverbs_idr_mutex); 259 256 260 257 return context->device->dealloc_ucontext(context); 261 258 }
+4
include/rdma/ib_verbs.h
··· 697 697 struct ib_uobject { 698 698 u64 user_handle; /* handle given to us by userspace */ 699 699 struct ib_ucontext *context; /* associated user context */ 700 + void *object; /* containing object */ 700 701 struct list_head list; /* link to context's list */ 701 702 u32 id; /* index into kernel idr */ 703 + struct kref ref; 704 + struct rw_semaphore mutex; /* protects .live */ 705 + int live; 702 706 }; 703 707 704 708 struct ib_umem {