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

IB/uverbs: Enable device removal when there are active user space applications

Enables the uverbs_remove_one to succeed despite the fact that there are
running IB applications working with the given ib device. This
functionality enables a HW device to be unbind/reset despite the fact that
there are running user space applications using it.

It exposes a new IB kernel API named 'disassociate_ucontext' which lets
a driver detaching its HW resources from a given user context without
crashing/terminating the application. In case a driver implemented the
above API and registered with ib_uverb there will be no dependency between its
device to its uverbs_device. Upon calling remove_one of ib_uverbs the call
should return after disassociating the open HW resources without waiting to
clients disconnecting. In case driver didn't implement this API there will be no
change to current behaviour and uverbs_remove_one will return only when last
client has disconnected and reference count on uverbs device became 0.

In case the lower driver device was removed any application will
continue working over some zombie HCA, further calls will ended with an
immediate error.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Shachar Raindel <raindel@mellanox.com>
Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Yishai Hadas and committed by
Doug Ledford
036b1063 057aec0d

+301 -67
+8 -1
drivers/infiniband/core/uverbs.h
··· 89 89 int num_comp_vectors; 90 90 struct completion comp; 91 91 struct device *dev; 92 - struct ib_device *ib_dev; 92 + struct ib_device __rcu *ib_dev; 93 93 int devnum; 94 94 struct cdev cdev; 95 95 struct rb_root xrcd_tree; 96 96 struct mutex xrcd_tree_mutex; 97 97 struct kobject kobj; 98 + struct srcu_struct disassociate_srcu; 99 + struct mutex lists_mutex; /* protect lists */ 100 + struct list_head uverbs_file_list; 101 + struct list_head uverbs_events_file_list; 98 102 }; 99 103 100 104 struct ib_uverbs_event_file { ··· 110 106 wait_queue_head_t poll_wait; 111 107 struct fasync_struct *async_queue; 112 108 struct list_head event_list; 109 + struct list_head list; 113 110 }; 114 111 115 112 struct ib_uverbs_file { ··· 120 115 struct ib_ucontext *ucontext; 121 116 struct ib_event_handler event_handler; 122 117 struct ib_uverbs_event_file *async_file; 118 + struct list_head list; 119 + int is_closed; 123 120 }; 124 121 125 122 struct ib_uverbs_event {
+292 -66
drivers/infiniband/core/uverbs_main.c
··· 137 137 struct ib_uverbs_device *dev = 138 138 container_of(kobj, struct ib_uverbs_device, kobj); 139 139 140 + cleanup_srcu_struct(&dev->disassociate_srcu); 140 141 kfree(dev); 141 142 } 142 143 ··· 207 206 struct ib_ucontext *context) 208 207 { 209 208 struct ib_uobject *uobj, *tmp; 210 - 211 - if (!context) 212 - return 0; 213 209 214 210 context->closing = 1; 215 211 ··· 316 318 { 317 319 struct ib_uverbs_file *file = 318 320 container_of(ref, struct ib_uverbs_file, ref); 321 + struct ib_device *ib_dev; 322 + int srcu_key; 319 323 320 - module_put(file->device->ib_dev->owner); 324 + srcu_key = srcu_read_lock(&file->device->disassociate_srcu); 325 + ib_dev = srcu_dereference(file->device->ib_dev, 326 + &file->device->disassociate_srcu); 327 + if (ib_dev && !ib_dev->disassociate_ucontext) 328 + module_put(ib_dev->owner); 329 + srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); 330 + 321 331 if (atomic_dec_and_test(&file->device->refcount)) 322 332 ib_uverbs_comp_dev(file->device); 323 333 ··· 349 343 return -EAGAIN; 350 344 351 345 if (wait_event_interruptible(file->poll_wait, 352 - !list_empty(&file->event_list))) 346 + (!list_empty(&file->event_list) || 347 + /* The barriers built into wait_event_interruptible() 348 + * and wake_up() guarentee this will see the null set 349 + * without using RCU 350 + */ 351 + !file->uverbs_file->device->ib_dev))) 353 352 return -ERESTARTSYS; 353 + 354 + /* If device was disassociated and no event exists set an error */ 355 + if (list_empty(&file->event_list) && 356 + !file->uverbs_file->device->ib_dev) 357 + return -EIO; 354 358 355 359 spin_lock_irq(&file->lock); 356 360 } ··· 424 408 { 425 409 struct ib_uverbs_event_file *file = filp->private_data; 426 410 struct ib_uverbs_event *entry, *tmp; 411 + int closed_already = 0; 427 412 413 + mutex_lock(&file->uverbs_file->device->lists_mutex); 428 414 spin_lock_irq(&file->lock); 415 + closed_already = file->is_closed; 429 416 file->is_closed = 1; 430 417 list_for_each_entry_safe(entry, tmp, &file->event_list, list) { 431 418 if (entry->counter) ··· 436 417 kfree(entry); 437 418 } 438 419 spin_unlock_irq(&file->lock); 420 + if (!closed_already) { 421 + list_del(&file->list); 422 + if (file->is_async) 423 + ib_unregister_event_handler(&file->uverbs_file-> 424 + event_handler); 425 + } 426 + mutex_unlock(&file->uverbs_file->device->lists_mutex); 439 427 440 - if (file->is_async) 441 - ib_unregister_event_handler(&file->uverbs_file->event_handler); 442 428 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file); 443 429 kref_put(&file->ref, ib_uverbs_release_event_file); 444 430 ··· 608 584 if (IS_ERR(filp)) 609 585 goto err_put_refs; 610 586 587 + mutex_lock(&uverbs_file->device->lists_mutex); 588 + list_add_tail(&ev_file->list, 589 + &uverbs_file->device->uverbs_events_file_list); 590 + mutex_unlock(&uverbs_file->device->lists_mutex); 591 + 611 592 if (is_async) { 612 593 WARN_ON(uverbs_file->async_file); 613 594 uverbs_file->async_file = ev_file; ··· 675 646 size_t count, loff_t *pos) 676 647 { 677 648 struct ib_uverbs_file *file = filp->private_data; 678 - struct ib_device *ib_dev = file->device->ib_dev; 649 + struct ib_device *ib_dev; 679 650 struct ib_uverbs_cmd_hdr hdr; 680 651 __u32 flags; 681 - 682 - if (!ib_dev) 683 - return -ENODEV; 652 + int srcu_key; 653 + ssize_t ret; 684 654 685 655 if (count < sizeof hdr) 686 656 return -EINVAL; 687 657 688 658 if (copy_from_user(&hdr, buf, sizeof hdr)) 689 659 return -EFAULT; 660 + 661 + srcu_key = srcu_read_lock(&file->device->disassociate_srcu); 662 + ib_dev = srcu_dereference(file->device->ib_dev, 663 + &file->device->disassociate_srcu); 664 + if (!ib_dev) { 665 + ret = -EIO; 666 + goto out; 667 + } 690 668 691 669 flags = (hdr.command & 692 670 IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT; ··· 702 666 __u32 command; 703 667 704 668 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK | 705 - IB_USER_VERBS_CMD_COMMAND_MASK)) 706 - return -EINVAL; 669 + IB_USER_VERBS_CMD_COMMAND_MASK)) { 670 + ret = -EINVAL; 671 + goto out; 672 + } 707 673 708 674 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK; 709 675 710 676 if (command >= ARRAY_SIZE(uverbs_cmd_table) || 711 - !uverbs_cmd_table[command]) 712 - return -EINVAL; 677 + !uverbs_cmd_table[command]) { 678 + ret = -EINVAL; 679 + goto out; 680 + } 713 681 714 682 if (!file->ucontext && 715 - command != IB_USER_VERBS_CMD_GET_CONTEXT) 716 - return -EINVAL; 683 + command != IB_USER_VERBS_CMD_GET_CONTEXT) { 684 + ret = -EINVAL; 685 + goto out; 686 + } 717 687 718 - if (!(ib_dev->uverbs_cmd_mask & (1ull << command))) 719 - return -ENOSYS; 688 + if (!(ib_dev->uverbs_cmd_mask & (1ull << command))) { 689 + ret = -ENOSYS; 690 + goto out; 691 + } 720 692 721 - if (hdr.in_words * 4 != count) 722 - return -EINVAL; 693 + if (hdr.in_words * 4 != count) { 694 + ret = -EINVAL; 695 + goto out; 696 + } 723 697 724 - return uverbs_cmd_table[command](file, ib_dev, 698 + ret = uverbs_cmd_table[command](file, ib_dev, 725 699 buf + sizeof(hdr), 726 700 hdr.in_words * 4, 727 701 hdr.out_words * 4); ··· 742 696 struct ib_uverbs_ex_cmd_hdr ex_hdr; 743 697 struct ib_udata ucore; 744 698 struct ib_udata uhw; 745 - int err; 746 699 size_t written_count = count; 747 700 748 701 if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK | 749 - IB_USER_VERBS_CMD_COMMAND_MASK)) 750 - return -EINVAL; 702 + IB_USER_VERBS_CMD_COMMAND_MASK)) { 703 + ret = -EINVAL; 704 + goto out; 705 + } 751 706 752 707 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK; 753 708 754 709 if (command >= ARRAY_SIZE(uverbs_ex_cmd_table) || 755 - !uverbs_ex_cmd_table[command]) 756 - return -ENOSYS; 710 + !uverbs_ex_cmd_table[command]) { 711 + ret = -ENOSYS; 712 + goto out; 713 + } 757 714 758 - if (!file->ucontext) 759 - return -EINVAL; 715 + if (!file->ucontext) { 716 + ret = -EINVAL; 717 + goto out; 718 + } 760 719 761 - if (!(ib_dev->uverbs_ex_cmd_mask & (1ull << command))) 762 - return -ENOSYS; 720 + if (!(ib_dev->uverbs_ex_cmd_mask & (1ull << command))) { 721 + ret = -ENOSYS; 722 + goto out; 723 + } 763 724 764 - if (count < (sizeof(hdr) + sizeof(ex_hdr))) 765 - return -EINVAL; 725 + if (count < (sizeof(hdr) + sizeof(ex_hdr))) { 726 + ret = -EINVAL; 727 + goto out; 728 + } 766 729 767 - if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr))) 768 - return -EFAULT; 730 + if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr))) { 731 + ret = -EFAULT; 732 + goto out; 733 + } 769 734 770 735 count -= sizeof(hdr) + sizeof(ex_hdr); 771 736 buf += sizeof(hdr) + sizeof(ex_hdr); 772 737 773 - if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) 774 - return -EINVAL; 738 + if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) { 739 + ret = -EINVAL; 740 + goto out; 741 + } 775 742 776 - if (ex_hdr.cmd_hdr_reserved) 777 - return -EINVAL; 743 + if (ex_hdr.cmd_hdr_reserved) { 744 + ret = -EINVAL; 745 + goto out; 746 + } 778 747 779 748 if (ex_hdr.response) { 780 - if (!hdr.out_words && !ex_hdr.provider_out_words) 781 - return -EINVAL; 749 + if (!hdr.out_words && !ex_hdr.provider_out_words) { 750 + ret = -EINVAL; 751 + goto out; 752 + } 782 753 783 754 if (!access_ok(VERIFY_WRITE, 784 755 (void __user *) (unsigned long) ex_hdr.response, 785 - (hdr.out_words + ex_hdr.provider_out_words) * 8)) 786 - return -EFAULT; 756 + (hdr.out_words + ex_hdr.provider_out_words) * 8)) { 757 + ret = -EFAULT; 758 + goto out; 759 + } 787 760 } else { 788 - if (hdr.out_words || ex_hdr.provider_out_words) 789 - return -EINVAL; 761 + if (hdr.out_words || ex_hdr.provider_out_words) { 762 + ret = -EINVAL; 763 + goto out; 764 + } 790 765 } 791 766 792 767 INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response, ··· 819 752 ex_hdr.provider_in_words * 8, 820 753 ex_hdr.provider_out_words * 8); 821 754 822 - err = uverbs_ex_cmd_table[command](file, 755 + ret = uverbs_ex_cmd_table[command](file, 823 756 ib_dev, 824 757 &ucore, 825 758 &uhw); 826 - 827 - if (err) 828 - return err; 829 - 830 - return written_count; 759 + if (!ret) 760 + ret = written_count; 761 + } else { 762 + ret = -ENOSYS; 831 763 } 832 764 833 - return -ENOSYS; 765 + out: 766 + srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); 767 + return ret; 834 768 } 835 769 836 770 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) 837 771 { 838 772 struct ib_uverbs_file *file = filp->private_data; 839 - struct ib_device *ib_dev = file->device->ib_dev; 773 + struct ib_device *ib_dev; 774 + int ret = 0; 775 + int srcu_key; 840 776 841 - if (!ib_dev || !file->ucontext) 842 - return -ENODEV; 777 + srcu_key = srcu_read_lock(&file->device->disassociate_srcu); 778 + ib_dev = srcu_dereference(file->device->ib_dev, 779 + &file->device->disassociate_srcu); 780 + if (!ib_dev) { 781 + ret = -EIO; 782 + goto out; 783 + } 784 + 785 + if (!file->ucontext) 786 + ret = -ENODEV; 843 787 else 844 - return ib_dev->mmap(file->ucontext, vma); 788 + ret = ib_dev->mmap(file->ucontext, vma); 789 + out: 790 + srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); 791 + return ret; 845 792 } 846 793 847 794 /* ··· 872 791 { 873 792 struct ib_uverbs_device *dev; 874 793 struct ib_uverbs_file *file; 794 + struct ib_device *ib_dev; 875 795 int ret; 796 + int module_dependent; 797 + int srcu_key; 876 798 877 799 dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev); 878 800 if (!atomic_inc_not_zero(&dev->refcount)) 879 801 return -ENXIO; 880 802 881 - if (!try_module_get(dev->ib_dev->owner)) { 882 - ret = -ENODEV; 803 + srcu_key = srcu_read_lock(&dev->disassociate_srcu); 804 + mutex_lock(&dev->lists_mutex); 805 + ib_dev = srcu_dereference(dev->ib_dev, 806 + &dev->disassociate_srcu); 807 + if (!ib_dev) { 808 + ret = -EIO; 883 809 goto err; 884 810 } 885 811 886 - file = kmalloc(sizeof *file, GFP_KERNEL); 812 + /* In case IB device supports disassociate ucontext, there is no hard 813 + * dependency between uverbs device and its low level device. 814 + */ 815 + module_dependent = !(ib_dev->disassociate_ucontext); 816 + 817 + if (module_dependent) { 818 + if (!try_module_get(ib_dev->owner)) { 819 + ret = -ENODEV; 820 + goto err; 821 + } 822 + } 823 + 824 + file = kzalloc(sizeof(*file), GFP_KERNEL); 887 825 if (!file) { 888 826 ret = -ENOMEM; 889 - goto err_module; 827 + if (module_dependent) 828 + goto err_module; 829 + 830 + goto err; 890 831 } 891 832 892 833 file->device = dev; ··· 919 816 920 817 filp->private_data = file; 921 818 kobject_get(&dev->kobj); 819 + list_add_tail(&file->list, &dev->uverbs_file_list); 820 + mutex_unlock(&dev->lists_mutex); 821 + srcu_read_unlock(&dev->disassociate_srcu, srcu_key); 922 822 923 823 return nonseekable_open(inode, filp); 924 824 925 825 err_module: 926 - module_put(dev->ib_dev->owner); 826 + module_put(ib_dev->owner); 927 827 928 828 err: 829 + mutex_unlock(&dev->lists_mutex); 830 + srcu_read_unlock(&dev->disassociate_srcu, srcu_key); 929 831 if (atomic_dec_and_test(&dev->refcount)) 930 832 ib_uverbs_comp_dev(dev); 931 833 ··· 941 833 { 942 834 struct ib_uverbs_file *file = filp->private_data; 943 835 struct ib_uverbs_device *dev = file->device; 836 + struct ib_ucontext *ucontext = NULL; 944 837 945 - ib_uverbs_cleanup_ucontext(file, file->ucontext); 838 + mutex_lock(&file->device->lists_mutex); 839 + ucontext = file->ucontext; 840 + file->ucontext = NULL; 841 + if (!file->is_closed) { 842 + list_del(&file->list); 843 + file->is_closed = 1; 844 + } 845 + mutex_unlock(&file->device->lists_mutex); 846 + if (ucontext) 847 + ib_uverbs_cleanup_ucontext(file, ucontext); 946 848 947 849 if (file->async_file) 948 850 kref_put(&file->async_file->ref, ib_uverbs_release_event_file); ··· 989 871 static ssize_t show_ibdev(struct device *device, struct device_attribute *attr, 990 872 char *buf) 991 873 { 874 + int ret = -ENODEV; 875 + int srcu_key; 992 876 struct ib_uverbs_device *dev = dev_get_drvdata(device); 877 + struct ib_device *ib_dev; 993 878 994 879 if (!dev) 995 880 return -ENODEV; 996 881 997 - return sprintf(buf, "%s\n", dev->ib_dev->name); 882 + srcu_key = srcu_read_lock(&dev->disassociate_srcu); 883 + ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); 884 + if (ib_dev) 885 + ret = sprintf(buf, "%s\n", ib_dev->name); 886 + srcu_read_unlock(&dev->disassociate_srcu, srcu_key); 887 + 888 + return ret; 998 889 } 999 890 static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 1000 891 ··· 1011 884 struct device_attribute *attr, char *buf) 1012 885 { 1013 886 struct ib_uverbs_device *dev = dev_get_drvdata(device); 887 + int ret = -ENODEV; 888 + int srcu_key; 889 + struct ib_device *ib_dev; 1014 890 1015 891 if (!dev) 1016 892 return -ENODEV; 893 + srcu_key = srcu_read_lock(&dev->disassociate_srcu); 894 + ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); 895 + if (ib_dev) 896 + ret = sprintf(buf, "%d\n", ib_dev->uverbs_abi_ver); 897 + srcu_read_unlock(&dev->disassociate_srcu, srcu_key); 1017 898 1018 - return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver); 899 + return ret; 1019 900 } 1020 901 static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); 1021 902 ··· 1063 928 int devnum; 1064 929 dev_t base; 1065 930 struct ib_uverbs_device *uverbs_dev; 931 + int ret; 1066 932 1067 933 if (!device->alloc_ucontext) 1068 934 return; ··· 1072 936 if (!uverbs_dev) 1073 937 return; 1074 938 939 + ret = init_srcu_struct(&uverbs_dev->disassociate_srcu); 940 + if (ret) { 941 + kfree(uverbs_dev); 942 + return; 943 + } 944 + 1075 945 atomic_set(&uverbs_dev->refcount, 1); 1076 946 init_completion(&uverbs_dev->comp); 1077 947 uverbs_dev->xrcd_tree = RB_ROOT; 1078 948 mutex_init(&uverbs_dev->xrcd_tree_mutex); 1079 949 kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype); 950 + mutex_init(&uverbs_dev->lists_mutex); 951 + INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); 952 + INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); 1080 953 1081 954 spin_lock(&map_lock); 1082 955 devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); ··· 1106 961 } 1107 962 spin_unlock(&map_lock); 1108 963 1109 - uverbs_dev->ib_dev = device; 964 + rcu_assign_pointer(uverbs_dev->ib_dev, device); 1110 965 uverbs_dev->num_comp_vectors = device->num_comp_vectors; 1111 966 1112 967 cdev_init(&uverbs_dev->cdev, NULL); ··· 1150 1005 return; 1151 1006 } 1152 1007 1008 + static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev, 1009 + struct ib_device *ib_dev) 1010 + { 1011 + struct ib_uverbs_file *file; 1012 + struct ib_uverbs_event_file *event_file; 1013 + struct ib_event event; 1014 + 1015 + /* Pending running commands to terminate */ 1016 + synchronize_srcu(&uverbs_dev->disassociate_srcu); 1017 + event.event = IB_EVENT_DEVICE_FATAL; 1018 + event.element.port_num = 0; 1019 + event.device = ib_dev; 1020 + 1021 + mutex_lock(&uverbs_dev->lists_mutex); 1022 + while (!list_empty(&uverbs_dev->uverbs_file_list)) { 1023 + struct ib_ucontext *ucontext; 1024 + 1025 + file = list_first_entry(&uverbs_dev->uverbs_file_list, 1026 + struct ib_uverbs_file, list); 1027 + file->is_closed = 1; 1028 + ucontext = file->ucontext; 1029 + list_del(&file->list); 1030 + file->ucontext = NULL; 1031 + kref_get(&file->ref); 1032 + mutex_unlock(&uverbs_dev->lists_mutex); 1033 + /* We must release the mutex before going ahead and calling 1034 + * disassociate_ucontext. disassociate_ucontext might end up 1035 + * indirectly calling uverbs_close, for example due to freeing 1036 + * the resources (e.g mmput). 1037 + */ 1038 + ib_uverbs_event_handler(&file->event_handler, &event); 1039 + if (ucontext) { 1040 + ib_dev->disassociate_ucontext(ucontext); 1041 + ib_uverbs_cleanup_ucontext(file, ucontext); 1042 + } 1043 + 1044 + mutex_lock(&uverbs_dev->lists_mutex); 1045 + kref_put(&file->ref, ib_uverbs_release_file); 1046 + } 1047 + 1048 + while (!list_empty(&uverbs_dev->uverbs_events_file_list)) { 1049 + event_file = list_first_entry(&uverbs_dev-> 1050 + uverbs_events_file_list, 1051 + struct ib_uverbs_event_file, 1052 + list); 1053 + spin_lock_irq(&event_file->lock); 1054 + event_file->is_closed = 1; 1055 + spin_unlock_irq(&event_file->lock); 1056 + 1057 + list_del(&event_file->list); 1058 + if (event_file->is_async) { 1059 + ib_unregister_event_handler(&event_file->uverbs_file-> 1060 + event_handler); 1061 + event_file->uverbs_file->event_handler.device = NULL; 1062 + } 1063 + 1064 + wake_up_interruptible(&event_file->poll_wait); 1065 + kill_fasync(&event_file->async_queue, SIGIO, POLL_IN); 1066 + } 1067 + mutex_unlock(&uverbs_dev->lists_mutex); 1068 + } 1069 + 1153 1070 static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) 1154 1071 { 1155 1072 struct ib_uverbs_device *uverbs_dev = client_data; 1073 + int wait_clients = 1; 1156 1074 1157 1075 if (!uverbs_dev) 1158 1076 return; ··· 1229 1021 else 1230 1022 clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map); 1231 1023 1024 + if (device->disassociate_ucontext) { 1025 + /* We disassociate HW resources and immediately return. 1026 + * Userspace will see a EIO errno for all future access. 1027 + * Upon returning, ib_device may be freed internally and is not 1028 + * valid any more. 1029 + * uverbs_device is still available until all clients close 1030 + * their files, then the uverbs device ref count will be zero 1031 + * and its resources will be freed. 1032 + * Note: At this point no more files can be opened since the 1033 + * cdev was deleted, however active clients can still issue 1034 + * commands and close their open files. 1035 + */ 1036 + rcu_assign_pointer(uverbs_dev->ib_dev, NULL); 1037 + ib_uverbs_free_hw_resources(uverbs_dev, device); 1038 + wait_clients = 0; 1039 + } 1040 + 1232 1041 if (atomic_dec_and_test(&uverbs_dev->refcount)) 1233 1042 ib_uverbs_comp_dev(uverbs_dev); 1234 - wait_for_completion(&uverbs_dev->comp); 1043 + if (wait_clients) 1044 + wait_for_completion(&uverbs_dev->comp); 1235 1045 kobject_put(&uverbs_dev->kobj); 1236 1046 } 1237 1047
+1
include/rdma/ib_verbs.h
··· 1769 1769 int (*destroy_flow)(struct ib_flow *flow_id); 1770 1770 int (*check_mr_status)(struct ib_mr *mr, u32 check_mask, 1771 1771 struct ib_mr_status *mr_status); 1772 + void (*disassociate_ucontext)(struct ib_ucontext *ibcontext); 1772 1773 1773 1774 struct ib_dma_mapping_ops *dma_ops; 1774 1775