diff options
| author | Shachar Raindel <raindel@mellanox.com> | 2014-12-11 10:04:17 -0500 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2014-12-15 21:13:36 -0500 |
| commit | 8ada2c1c0c1d75a60723cd2ca7d49c594a146af6 (patch) | |
| tree | a80d10bb8cf4888a7f6313698a40980de5724b51 /drivers | |
| parent | 860f10a799c83e38a69d5a69d80da5312a4c4106 (diff) | |
IB/core: Add support for on demand paging regions
* Extend the umem struct to keep the ODP related data.
* Allocate and initialize the ODP related information in the umem
(page_list, dma_list) and freeing as needed in the end of the run.
* Store a reference to the process PID struct in the ucontext. Used to
safely obtain the task_struct and the mm during fault handling,
without preventing the task destruction if needed.
* Add 2 helper functions: ib_umem_odp_map_dma_pages and
ib_umem_odp_unmap_dma_pages. These functions get the DMA addresses
of specific pages of the umem (and, currently, pin them).
* Support for page faults only - IB core will keep the reference on
the pages used and call put_page when freeing an ODP umem
area. Invalidations support will be added in a later patch.
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Shachar Raindel <raindel@mellanox.com>
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Majd Dibbiny <majd@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/infiniband/core/Makefile | 1 | ||||
| -rw-r--r-- | drivers/infiniband/core/umem.c | 24 | ||||
| -rw-r--r-- | drivers/infiniband/core/umem_odp.c | 309 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 5 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 2 |
5 files changed, 341 insertions, 0 deletions
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile index ffd0af6734af..c58f7913c560 100644 --- a/drivers/infiniband/core/Makefile +++ b/drivers/infiniband/core/Makefile | |||
| @@ -11,6 +11,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ | |||
| 11 | ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ | 11 | ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ |
| 12 | device.o fmr_pool.o cache.o netlink.o | 12 | device.o fmr_pool.o cache.o netlink.o |
| 13 | ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o | 13 | ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o |
| 14 | ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o | ||
| 14 | 15 | ||
| 15 | ib_mad-y := mad.o smi.o agent.o mad_rmpp.o | 16 | ib_mad-y := mad.o smi.o agent.o mad_rmpp.o |
| 16 | 17 | ||
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index c328e4693d14..5baceb79f21b 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/hugetlb.h> | 39 | #include <linux/hugetlb.h> |
| 40 | #include <linux/dma-attrs.h> | 40 | #include <linux/dma-attrs.h> |
| 41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 42 | #include <rdma/ib_umem_odp.h> | ||
| 42 | 43 | ||
| 43 | #include "uverbs.h" | 44 | #include "uverbs.h" |
| 44 | 45 | ||
| @@ -69,6 +70,10 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d | |||
| 69 | 70 | ||
| 70 | /** | 71 | /** |
| 71 | * ib_umem_get - Pin and DMA map userspace memory. | 72 | * ib_umem_get - Pin and DMA map userspace memory. |
| 73 | * | ||
| 74 | * If access flags indicate ODP memory, avoid pinning. Instead, stores | ||
| 75 | * the mm for future page fault handling. | ||
| 76 | * | ||
| 72 | * @context: userspace context to pin memory for | 77 | * @context: userspace context to pin memory for |
| 73 | * @addr: userspace virtual address to start at | 78 | * @addr: userspace virtual address to start at |
| 74 | * @size: length of region to pin | 79 | * @size: length of region to pin |
| @@ -117,6 +122,17 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, | |||
| 117 | (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | | 122 | (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | |
| 118 | IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND)); | 123 | IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND)); |
| 119 | 124 | ||
| 125 | if (access & IB_ACCESS_ON_DEMAND) { | ||
| 126 | ret = ib_umem_odp_get(context, umem); | ||
| 127 | if (ret) { | ||
| 128 | kfree(umem); | ||
| 129 | return ERR_PTR(ret); | ||
| 130 | } | ||
| 131 | return umem; | ||
| 132 | } | ||
| 133 | |||
| 134 | umem->odp_data = NULL; | ||
| 135 | |||
| 120 | /* We assume the memory is from hugetlb until proved otherwise */ | 136 | /* We assume the memory is from hugetlb until proved otherwise */ |
| 121 | umem->hugetlb = 1; | 137 | umem->hugetlb = 1; |
| 122 | 138 | ||
| @@ -237,6 +253,11 @@ void ib_umem_release(struct ib_umem *umem) | |||
| 237 | struct task_struct *task; | 253 | struct task_struct *task; |
| 238 | unsigned long diff; | 254 | unsigned long diff; |
| 239 | 255 | ||
| 256 | if (umem->odp_data) { | ||
| 257 | ib_umem_odp_release(umem); | ||
| 258 | return; | ||
| 259 | } | ||
| 260 | |||
| 240 | __ib_umem_release(umem->context->device, umem, 1); | 261 | __ib_umem_release(umem->context->device, umem, 1); |
| 241 | 262 | ||
| 242 | task = get_pid_task(umem->pid, PIDTYPE_PID); | 263 | task = get_pid_task(umem->pid, PIDTYPE_PID); |
| @@ -285,6 +306,9 @@ int ib_umem_page_count(struct ib_umem *umem) | |||
| 285 | int n; | 306 | int n; |
| 286 | struct scatterlist *sg; | 307 | struct scatterlist *sg; |
| 287 | 308 | ||
| 309 | if (umem->odp_data) | ||
| 310 | return ib_umem_num_pages(umem); | ||
| 311 | |||
| 288 | shift = ilog2(umem->page_size); | 312 | shift = ilog2(umem->page_size); |
| 289 | 313 | ||
| 290 | n = 0; | 314 | n = 0; |
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c new file mode 100644 index 000000000000..f889e8d793bd --- /dev/null +++ b/drivers/infiniband/core/umem_odp.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Mellanox Technologies. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the | ||
| 8 | * OpenIB.org BSD license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or | ||
| 11 | * without modification, are permitted provided that the following | ||
| 12 | * conditions are met: | ||
| 13 | * | ||
| 14 | * - Redistributions of source code must retain the above | ||
| 15 | * copyright notice, this list of conditions and the following | ||
| 16 | * disclaimer. | ||
| 17 | * | ||
| 18 | * - Redistributions in binary form must reproduce the above | ||
| 19 | * copyright notice, this list of conditions and the following | ||
| 20 | * disclaimer in the documentation and/or other materials | ||
| 21 | * provided with the distribution. | ||
| 22 | * | ||
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 30 | * SOFTWARE. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/types.h> | ||
| 34 | #include <linux/sched.h> | ||
| 35 | #include <linux/pid.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/export.h> | ||
| 38 | #include <linux/vmalloc.h> | ||
| 39 | |||
| 40 | #include <rdma/ib_verbs.h> | ||
| 41 | #include <rdma/ib_umem.h> | ||
| 42 | #include <rdma/ib_umem_odp.h> | ||
| 43 | |||
| 44 | int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem) | ||
| 45 | { | ||
| 46 | int ret_val; | ||
| 47 | struct pid *our_pid; | ||
| 48 | |||
| 49 | /* Prevent creating ODP MRs in child processes */ | ||
| 50 | rcu_read_lock(); | ||
| 51 | our_pid = get_task_pid(current->group_leader, PIDTYPE_PID); | ||
| 52 | rcu_read_unlock(); | ||
| 53 | put_pid(our_pid); | ||
| 54 | if (context->tgid != our_pid) | ||
| 55 | return -EINVAL; | ||
| 56 | |||
| 57 | umem->hugetlb = 0; | ||
| 58 | umem->odp_data = kzalloc(sizeof(*umem->odp_data), GFP_KERNEL); | ||
| 59 | if (!umem->odp_data) | ||
| 60 | return -ENOMEM; | ||
| 61 | |||
| 62 | mutex_init(&umem->odp_data->umem_mutex); | ||
| 63 | |||
| 64 | umem->odp_data->page_list = vzalloc(ib_umem_num_pages(umem) * | ||
| 65 | sizeof(*umem->odp_data->page_list)); | ||
| 66 | if (!umem->odp_data->page_list) { | ||
| 67 | ret_val = -ENOMEM; | ||
| 68 | goto out_odp_data; | ||
| 69 | } | ||
| 70 | |||
| 71 | umem->odp_data->dma_list = vzalloc(ib_umem_num_pages(umem) * | ||
| 72 | sizeof(*umem->odp_data->dma_list)); | ||
| 73 | if (!umem->odp_data->dma_list) { | ||
| 74 | ret_val = -ENOMEM; | ||
| 75 | goto out_page_list; | ||
| 76 | } | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | |||
| 80 | out_page_list: | ||
| 81 | vfree(umem->odp_data->page_list); | ||
| 82 | out_odp_data: | ||
| 83 | kfree(umem->odp_data); | ||
| 84 | return ret_val; | ||
| 85 | } | ||
| 86 | |||
| 87 | void ib_umem_odp_release(struct ib_umem *umem) | ||
| 88 | { | ||
| 89 | /* | ||
| 90 | * Ensure that no more pages are mapped in the umem. | ||
| 91 | * | ||
| 92 | * It is the driver's responsibility to ensure, before calling us, | ||
| 93 | * that the hardware will not attempt to access the MR any more. | ||
| 94 | */ | ||
| 95 | ib_umem_odp_unmap_dma_pages(umem, ib_umem_start(umem), | ||
| 96 | ib_umem_end(umem)); | ||
| 97 | |||
| 98 | vfree(umem->odp_data->dma_list); | ||
| 99 | vfree(umem->odp_data->page_list); | ||
| 100 | kfree(umem->odp_data); | ||
| 101 | kfree(umem); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Map for DMA and insert a single page into the on-demand paging page tables. | ||
| 106 | * | ||
| 107 | * @umem: the umem to insert the page to. | ||
| 108 | * @page_index: index in the umem to add the page to. | ||
| 109 | * @page: the page struct to map and add. | ||
| 110 | * @access_mask: access permissions needed for this page. | ||
| 111 | * @current_seq: sequence number for synchronization with invalidations. | ||
| 112 | * the sequence number is taken from | ||
| 113 | * umem->odp_data->notifiers_seq. | ||
| 114 | * | ||
| 115 | * The function returns -EFAULT if the DMA mapping operation fails. | ||
| 116 | * | ||
| 117 | * The page is released via put_page even if the operation failed. For | ||
| 118 | * on-demand pinning, the page is released whenever it isn't stored in the | ||
| 119 | * umem. | ||
| 120 | */ | ||
| 121 | static int ib_umem_odp_map_dma_single_page( | ||
| 122 | struct ib_umem *umem, | ||
| 123 | int page_index, | ||
| 124 | struct page *page, | ||
| 125 | u64 access_mask, | ||
| 126 | unsigned long current_seq) | ||
| 127 | { | ||
| 128 | struct ib_device *dev = umem->context->device; | ||
| 129 | dma_addr_t dma_addr; | ||
| 130 | int stored_page = 0; | ||
| 131 | int ret = 0; | ||
| 132 | |||
| 133 | mutex_lock(&umem->odp_data->umem_mutex); | ||
| 134 | if (!(umem->odp_data->dma_list[page_index])) { | ||
| 135 | dma_addr = ib_dma_map_page(dev, | ||
| 136 | page, | ||
| 137 | 0, PAGE_SIZE, | ||
| 138 | DMA_BIDIRECTIONAL); | ||
| 139 | if (ib_dma_mapping_error(dev, dma_addr)) { | ||
| 140 | ret = -EFAULT; | ||
| 141 | goto out; | ||
| 142 | } | ||
| 143 | umem->odp_data->dma_list[page_index] = dma_addr | access_mask; | ||
| 144 | umem->odp_data->page_list[page_index] = page; | ||
| 145 | stored_page = 1; | ||
| 146 | } else if (umem->odp_data->page_list[page_index] == page) { | ||
| 147 | umem->odp_data->dma_list[page_index] |= access_mask; | ||
| 148 | } else { | ||
| 149 | pr_err("error: got different pages in IB device and from get_user_pages. IB device page: %p, gup page: %p\n", | ||
| 150 | umem->odp_data->page_list[page_index], page); | ||
| 151 | } | ||
| 152 | |||
| 153 | out: | ||
| 154 | mutex_unlock(&umem->odp_data->umem_mutex); | ||
| 155 | |||
| 156 | if (!stored_page) | ||
| 157 | put_page(page); | ||
| 158 | |||
| 159 | return ret; | ||
| 160 | } | ||
| 161 | |||
| 162 | /** | ||
| 163 | * ib_umem_odp_map_dma_pages - Pin and DMA map userspace memory in an ODP MR. | ||
| 164 | * | ||
| 165 | * Pins the range of pages passed in the argument, and maps them to | ||
| 166 | * DMA addresses. The DMA addresses of the mapped pages is updated in | ||
| 167 | * umem->odp_data->dma_list. | ||
| 168 | * | ||
| 169 | * Returns the number of pages mapped in success, negative error code | ||
| 170 | * for failure. | ||
| 171 | * | ||
| 172 | * @umem: the umem to map and pin | ||
| 173 | * @user_virt: the address from which we need to map. | ||
| 174 | * @bcnt: the minimal number of bytes to pin and map. The mapping might be | ||
| 175 | * bigger due to alignment, and may also be smaller in case of an error | ||
| 176 | * pinning or mapping a page. The actual pages mapped is returned in | ||
| 177 | * the return value. | ||
| 178 | * @access_mask: bit mask of the requested access permissions for the given | ||
| 179 | * range. | ||
| 180 | * @current_seq: the MMU notifiers sequance value for synchronization with | ||
| 181 | * invalidations. the sequance number is read from | ||
| 182 | * umem->odp_data->notifiers_seq before calling this function | ||
| 183 | */ | ||
| 184 | int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt, | ||
| 185 | u64 access_mask, unsigned long current_seq) | ||
| 186 | { | ||
| 187 | struct task_struct *owning_process = NULL; | ||
| 188 | struct mm_struct *owning_mm = NULL; | ||
| 189 | struct page **local_page_list = NULL; | ||
| 190 | u64 off; | ||
| 191 | int j, k, ret = 0, start_idx, npages = 0; | ||
| 192 | |||
| 193 | if (access_mask == 0) | ||
| 194 | return -EINVAL; | ||
| 195 | |||
| 196 | if (user_virt < ib_umem_start(umem) || | ||
| 197 | user_virt + bcnt > ib_umem_end(umem)) | ||
| 198 | return -EFAULT; | ||
| 199 | |||
| 200 | local_page_list = (struct page **)__get_free_page(GFP_KERNEL); | ||
| 201 | if (!local_page_list) | ||
| 202 | return -ENOMEM; | ||
| 203 | |||
| 204 | off = user_virt & (~PAGE_MASK); | ||
| 205 | user_virt = user_virt & PAGE_MASK; | ||
| 206 | bcnt += off; /* Charge for the first page offset as well. */ | ||
| 207 | |||
| 208 | owning_process = get_pid_task(umem->context->tgid, PIDTYPE_PID); | ||
| 209 | if (owning_process == NULL) { | ||
| 210 | ret = -EINVAL; | ||
| 211 | goto out_no_task; | ||
| 212 | } | ||
| 213 | |||
| 214 | owning_mm = get_task_mm(owning_process); | ||
| 215 | if (owning_mm == NULL) { | ||
| 216 | ret = -EINVAL; | ||
| 217 | goto out_put_task; | ||
| 218 | } | ||
| 219 | |||
| 220 | start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT; | ||
| 221 | k = start_idx; | ||
| 222 | |||
| 223 | while (bcnt > 0) { | ||
| 224 | const size_t gup_num_pages = | ||
| 225 | min_t(size_t, ALIGN(bcnt, PAGE_SIZE) / PAGE_SIZE, | ||
| 226 | PAGE_SIZE / sizeof(struct page *)); | ||
| 227 | |||
| 228 | down_read(&owning_mm->mmap_sem); | ||
| 229 | /* | ||
| 230 | * Note: this might result in redundent page getting. We can | ||
| 231 | * avoid this by checking dma_list to be 0 before calling | ||
| 232 | * get_user_pages. However, this make the code much more | ||
| 233 | * complex (and doesn't gain us much performance in most use | ||
| 234 | * cases). | ||
| 235 | */ | ||
| 236 | npages = get_user_pages(owning_process, owning_mm, user_virt, | ||
| 237 | gup_num_pages, | ||
| 238 | access_mask & ODP_WRITE_ALLOWED_BIT, 0, | ||
| 239 | local_page_list, NULL); | ||
| 240 | up_read(&owning_mm->mmap_sem); | ||
| 241 | |||
| 242 | if (npages < 0) | ||
| 243 | break; | ||
| 244 | |||
| 245 | bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt); | ||
| 246 | user_virt += npages << PAGE_SHIFT; | ||
| 247 | for (j = 0; j < npages; ++j) { | ||
| 248 | ret = ib_umem_odp_map_dma_single_page( | ||
| 249 | umem, k, local_page_list[j], access_mask, | ||
| 250 | current_seq); | ||
| 251 | if (ret < 0) | ||
| 252 | break; | ||
| 253 | k++; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (ret < 0) { | ||
| 257 | /* Release left over pages when handling errors. */ | ||
| 258 | for (++j; j < npages; ++j) | ||
| 259 | put_page(local_page_list[j]); | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | if (ret >= 0) { | ||
| 265 | if (npages < 0 && k == start_idx) | ||
| 266 | ret = npages; | ||
| 267 | else | ||
| 268 | ret = k - start_idx; | ||
| 269 | } | ||
| 270 | |||
| 271 | mmput(owning_mm); | ||
| 272 | out_put_task: | ||
| 273 | put_task_struct(owning_process); | ||
| 274 | out_no_task: | ||
| 275 | free_page((unsigned long)local_page_list); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | EXPORT_SYMBOL(ib_umem_odp_map_dma_pages); | ||
| 279 | |||
| 280 | void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt, | ||
| 281 | u64 bound) | ||
| 282 | { | ||
| 283 | int idx; | ||
| 284 | u64 addr; | ||
| 285 | struct ib_device *dev = umem->context->device; | ||
| 286 | |||
| 287 | virt = max_t(u64, virt, ib_umem_start(umem)); | ||
| 288 | bound = min_t(u64, bound, ib_umem_end(umem)); | ||
| 289 | for (addr = virt; addr < bound; addr += (u64)umem->page_size) { | ||
| 290 | idx = (addr - ib_umem_start(umem)) / PAGE_SIZE; | ||
| 291 | mutex_lock(&umem->odp_data->umem_mutex); | ||
| 292 | if (umem->odp_data->page_list[idx]) { | ||
| 293 | struct page *page = umem->odp_data->page_list[idx]; | ||
| 294 | struct page *head_page = compound_head(page); | ||
| 295 | dma_addr_t dma = umem->odp_data->dma_list[idx]; | ||
| 296 | dma_addr_t dma_addr = dma & ODP_DMA_ADDR_MASK; | ||
| 297 | |||
| 298 | WARN_ON(!dma_addr); | ||
| 299 | |||
| 300 | ib_dma_unmap_page(dev, dma_addr, PAGE_SIZE, | ||
| 301 | DMA_BIDIRECTIONAL); | ||
| 302 | if (dma & ODP_WRITE_ALLOWED_BIT) | ||
| 303 | set_page_dirty_lock(head_page); | ||
| 304 | put_page(page); | ||
| 305 | } | ||
| 306 | mutex_unlock(&umem->odp_data->umem_mutex); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages); | ||
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index f9326ccda4b5..70b697d8fbb3 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/file.h> | 36 | #include <linux/file.h> |
| 37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/sched.h> | ||
| 39 | 40 | ||
| 40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
| 41 | 42 | ||
| @@ -325,6 +326,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
| 325 | INIT_LIST_HEAD(&ucontext->ah_list); | 326 | INIT_LIST_HEAD(&ucontext->ah_list); |
| 326 | INIT_LIST_HEAD(&ucontext->xrcd_list); | 327 | INIT_LIST_HEAD(&ucontext->xrcd_list); |
| 327 | INIT_LIST_HEAD(&ucontext->rule_list); | 328 | INIT_LIST_HEAD(&ucontext->rule_list); |
| 329 | rcu_read_lock(); | ||
| 330 | ucontext->tgid = get_task_pid(current->group_leader, PIDTYPE_PID); | ||
| 331 | rcu_read_unlock(); | ||
| 328 | ucontext->closing = 0; | 332 | ucontext->closing = 0; |
| 329 | 333 | ||
| 330 | resp.num_comp_vectors = file->device->num_comp_vectors; | 334 | resp.num_comp_vectors = file->device->num_comp_vectors; |
| @@ -371,6 +375,7 @@ err_fd: | |||
| 371 | put_unused_fd(resp.async_fd); | 375 | put_unused_fd(resp.async_fd); |
| 372 | 376 | ||
| 373 | err_free: | 377 | err_free: |
| 378 | put_pid(ucontext->tgid); | ||
| 374 | ibdev->dealloc_ucontext(ucontext); | 379 | ibdev->dealloc_ucontext(ucontext); |
| 375 | 380 | ||
| 376 | err: | 381 | err: |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 974025028790..e6c23b9eab33 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
| @@ -297,6 +297,8 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
| 297 | kfree(uobj); | 297 | kfree(uobj); |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | put_pid(context->tgid); | ||
| 301 | |||
| 300 | return context->device->dealloc_ucontext(context); | 302 | return context->device->dealloc_ucontext(context); |
| 301 | } | 303 | } |
| 302 | 304 | ||
