[PATCH] IB: fix userspace CM deadlock

Fix deadlock condition resulting from trying to destroy a cm_id
from the context of a CM thread. The synchronization around the
ucm context structure is simplified as a result, and some simple
code cleanup is included.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Sean Hefty and committed by
Roland Dreier
b9ef520f 4ce05937

+160 -313
+157 -307
drivers/infiniband/core/ucm.c
··· 1 1 /* 2 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 + * Copyright (c) 2005 Intel Corporation. All rights reserved. 3 4 * 4 5 * This software is available to you under a choice of one of two 5 6 * licenses. You may choose to be licensed under the terms of the GNU ··· 74 73 static struct idr ctx_id_table; 75 74 static int ctx_id_rover = 0; 76 75 77 - static struct ib_ucm_context *ib_ucm_ctx_get(int id) 76 + static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) 78 77 { 79 78 struct ib_ucm_context *ctx; 80 79 81 80 down(&ctx_id_mutex); 82 81 ctx = idr_find(&ctx_id_table, id); 83 - if (ctx) 84 - ctx->ref++; 82 + if (!ctx) 83 + ctx = ERR_PTR(-ENOENT); 84 + else if (ctx->file != file) 85 + ctx = ERR_PTR(-EINVAL); 86 + else 87 + atomic_inc(&ctx->ref); 85 88 up(&ctx_id_mutex); 86 89 87 90 return ctx; ··· 93 88 94 89 static void ib_ucm_ctx_put(struct ib_ucm_context *ctx) 95 90 { 91 + if (atomic_dec_and_test(&ctx->ref)) 92 + wake_up(&ctx->wait); 93 + } 94 + 95 + static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id) 96 + { 97 + struct ib_ucm_context *ctx; 96 98 struct ib_ucm_event *uevent; 97 99 98 100 down(&ctx_id_mutex); 99 - 100 - ctx->ref--; 101 - if (!ctx->ref) 101 + ctx = idr_find(&ctx_id_table, id); 102 + if (!ctx) 103 + ctx = ERR_PTR(-ENOENT); 104 + else if (ctx->file != file) 105 + ctx = ERR_PTR(-EINVAL); 106 + else 102 107 idr_remove(&ctx_id_table, ctx->id); 103 - 104 108 up(&ctx_id_mutex); 105 109 106 - if (ctx->ref) 107 - return; 110 + if (IS_ERR(ctx)) 111 + return PTR_ERR(ctx); 108 112 109 - down(&ctx->file->mutex); 113 + atomic_dec(&ctx->ref); 114 + wait_event(ctx->wait, !atomic_read(&ctx->ref)); 110 115 116 + /* No new events will be generated after destroying the cm_id. */ 117 + if (!IS_ERR(ctx->cm_id)) 118 + ib_destroy_cm_id(ctx->cm_id); 119 + 120 + /* Cleanup events not yet reported to the user. */ 121 + down(&file->mutex); 111 122 list_del(&ctx->file_list); 112 123 while (!list_empty(&ctx->events)) { 113 124 ··· 138 117 139 118 kfree(uevent); 140 119 } 120 + up(&file->mutex); 141 121 142 - up(&ctx->file->mutex); 143 - 144 - ucm_dbg("Destroyed CM ID <%d>\n", ctx->id); 145 - 146 - ib_destroy_cm_id(ctx->cm_id); 147 122 kfree(ctx); 123 + return 0; 148 124 } 149 125 150 126 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) ··· 153 135 if (!ctx) 154 136 return NULL; 155 137 156 - ctx->ref = 1; /* user reference */ 138 + atomic_set(&ctx->ref, 1); 139 + init_waitqueue_head(&ctx->wait); 157 140 ctx->file = file; 158 141 159 142 INIT_LIST_HEAD(&ctx->events); 160 - init_MUTEX(&ctx->mutex); 161 143 162 144 list_add_tail(&ctx->file_list, &file->ctxs); 163 145 ··· 195 177 if (!kpath || !upath) 196 178 return; 197 179 198 - memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid)); 199 - memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid)); 180 + memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid); 181 + memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid); 200 182 201 183 upath->dlid = kpath->dlid; 202 184 upath->slid = kpath->slid; ··· 219 201 kpath->packet_life_time_selector; 220 202 } 221 203 222 - static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq, 204 + static void ib_ucm_event_req_get(struct ib_ucm_context *ctx, 205 + struct ib_ucm_req_event_resp *ureq, 223 206 struct ib_cm_req_event_param *kreq) 224 207 { 225 - ureq->listen_id = (long)kreq->listen_id->context; 208 + ureq->listen_id = ctx->id; 226 209 227 210 ureq->remote_ca_guid = kreq->remote_ca_guid; 228 211 ureq->remote_qkey = kreq->remote_qkey; ··· 259 240 urep->srq = krep->srq; 260 241 } 261 242 262 - static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej, 263 - struct ib_cm_rej_event_param *krej) 264 - { 265 - urej->reason = krej->reason; 266 - } 267 - 268 - static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra, 269 - struct ib_cm_mra_event_param *kmra) 270 - { 271 - umra->timeout = kmra->service_timeout; 272 - } 273 - 274 - static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap, 275 - struct ib_cm_lap_event_param *klap) 276 - { 277 - ib_ucm_event_path_get(&ulap->path, klap->alternate_path); 278 - } 279 - 280 - static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr, 281 - struct ib_cm_apr_event_param *kapr) 282 - { 283 - uapr->status = kapr->ap_status; 284 - } 285 - 286 - static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq, 243 + static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx, 244 + struct ib_ucm_sidr_req_event_resp *ureq, 287 245 struct ib_cm_sidr_req_event_param *kreq) 288 246 { 289 - ureq->listen_id = (long)kreq->listen_id->context; 247 + ureq->listen_id = ctx->id; 290 248 ureq->pkey = kreq->pkey; 291 249 } 292 250 ··· 275 279 urep->qpn = krep->qpn; 276 280 }; 277 281 278 - static int ib_ucm_event_process(struct ib_cm_event *evt, 282 + static int ib_ucm_event_process(struct ib_ucm_context *ctx, 283 + struct ib_cm_event *evt, 279 284 struct ib_ucm_event *uvt) 280 285 { 281 286 void *info = NULL; 282 - int result; 283 287 284 288 switch (evt->event) { 285 289 case IB_CM_REQ_RECEIVED: 286 - ib_ucm_event_req_get(&uvt->resp.u.req_resp, 290 + ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp, 287 291 &evt->param.req_rcvd); 288 292 uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE; 289 - uvt->resp.present |= (evt->param.req_rcvd.primary_path ? 290 - IB_UCM_PRES_PRIMARY : 0); 293 + uvt->resp.present = IB_UCM_PRES_PRIMARY; 291 294 uvt->resp.present |= (evt->param.req_rcvd.alternate_path ? 292 295 IB_UCM_PRES_ALTERNATE : 0); 293 296 break; ··· 294 299 ib_ucm_event_rep_get(&uvt->resp.u.rep_resp, 295 300 &evt->param.rep_rcvd); 296 301 uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE; 297 - 298 302 break; 299 303 case IB_CM_RTU_RECEIVED: 300 304 uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE; 301 305 uvt->resp.u.send_status = evt->param.send_status; 302 - 303 306 break; 304 307 case IB_CM_DREQ_RECEIVED: 305 308 uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE; 306 309 uvt->resp.u.send_status = evt->param.send_status; 307 - 308 310 break; 309 311 case IB_CM_DREP_RECEIVED: 310 312 uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE; 311 313 uvt->resp.u.send_status = evt->param.send_status; 312 - 313 314 break; 314 315 case IB_CM_MRA_RECEIVED: 315 - ib_ucm_event_mra_get(&uvt->resp.u.mra_resp, 316 - &evt->param.mra_rcvd); 316 + uvt->resp.u.mra_resp.timeout = 317 + evt->param.mra_rcvd.service_timeout; 317 318 uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE; 318 - 319 319 break; 320 320 case IB_CM_REJ_RECEIVED: 321 - ib_ucm_event_rej_get(&uvt->resp.u.rej_resp, 322 - &evt->param.rej_rcvd); 321 + uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason; 323 322 uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; 324 323 uvt->info_len = evt->param.rej_rcvd.ari_length; 325 324 info = evt->param.rej_rcvd.ari; 326 - 327 325 break; 328 326 case IB_CM_LAP_RECEIVED: 329 - ib_ucm_event_lap_get(&uvt->resp.u.lap_resp, 330 - &evt->param.lap_rcvd); 327 + ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path, 328 + evt->param.lap_rcvd.alternate_path); 331 329 uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE; 332 - uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ? 333 - IB_UCM_PRES_ALTERNATE : 0); 330 + uvt->resp.present = IB_UCM_PRES_ALTERNATE; 334 331 break; 335 332 case IB_CM_APR_RECEIVED: 336 - ib_ucm_event_apr_get(&uvt->resp.u.apr_resp, 337 - &evt->param.apr_rcvd); 333 + uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status; 338 334 uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE; 339 335 uvt->info_len = evt->param.apr_rcvd.info_len; 340 336 info = evt->param.apr_rcvd.apr_info; 341 - 342 337 break; 343 338 case IB_CM_SIDR_REQ_RECEIVED: 344 - ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp, 339 + ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp, 345 340 &evt->param.sidr_req_rcvd); 346 341 uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; 347 - 348 342 break; 349 343 case IB_CM_SIDR_REP_RECEIVED: 350 344 ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp, ··· 341 357 uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE; 342 358 uvt->info_len = evt->param.sidr_rep_rcvd.info_len; 343 359 info = evt->param.sidr_rep_rcvd.info; 344 - 345 360 break; 346 361 default: 347 362 uvt->resp.u.send_status = evt->param.send_status; 348 - 349 363 break; 350 364 } 351 365 352 - if (uvt->data_len && evt->private_data) { 353 - 366 + if (uvt->data_len) { 354 367 uvt->data = kmalloc(uvt->data_len, GFP_KERNEL); 355 - if (!uvt->data) { 356 - result = -ENOMEM; 357 - goto error; 358 - } 368 + if (!uvt->data) 369 + goto err1; 359 370 360 371 memcpy(uvt->data, evt->private_data, uvt->data_len); 361 372 uvt->resp.present |= IB_UCM_PRES_DATA; 362 373 } 363 374 364 - if (uvt->info_len && info) { 365 - 375 + if (uvt->info_len) { 366 376 uvt->info = kmalloc(uvt->info_len, GFP_KERNEL); 367 - if (!uvt->info) { 368 - result = -ENOMEM; 369 - goto error; 370 - } 377 + if (!uvt->info) 378 + goto err2; 371 379 372 380 memcpy(uvt->info, info, uvt->info_len); 373 381 uvt->resp.present |= IB_UCM_PRES_INFO; 374 382 } 375 - 376 383 return 0; 377 - error: 378 - kfree(uvt->info); 384 + 385 + err2: 379 386 kfree(uvt->data); 380 - return result; 387 + err1: 388 + return -ENOMEM; 381 389 } 382 390 383 391 static int ib_ucm_event_handler(struct ib_cm_id *cm_id, ··· 379 403 struct ib_ucm_context *ctx; 380 404 int result = 0; 381 405 int id; 382 - /* 383 - * lookup correct context based on event type. 384 - */ 385 - switch (event->event) { 386 - case IB_CM_REQ_RECEIVED: 387 - id = (long)event->param.req_rcvd.listen_id->context; 388 - break; 389 - case IB_CM_SIDR_REQ_RECEIVED: 390 - id = (long)event->param.sidr_req_rcvd.listen_id->context; 391 - break; 392 - default: 393 - id = (long)cm_id->context; 394 - break; 395 - } 396 406 397 - ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event); 398 - 399 - ctx = ib_ucm_ctx_get(id); 400 - if (!ctx) 401 - return -ENOENT; 407 + ctx = cm_id->context; 402 408 403 409 if (event->event == IB_CM_REQ_RECEIVED || 404 410 event->event == IB_CM_SIDR_REQ_RECEIVED) 405 411 id = IB_UCM_CM_ID_INVALID; 412 + else 413 + id = ctx->id; 406 414 407 415 uevent = kmalloc(sizeof(*uevent), GFP_KERNEL); 408 - if (!uevent) { 409 - result = -ENOMEM; 410 - goto done; 411 - } 416 + if (!uevent) 417 + goto err1; 412 418 413 419 memset(uevent, 0, sizeof(*uevent)); 414 - 415 420 uevent->resp.id = id; 416 421 uevent->resp.event = event->event; 417 422 418 - result = ib_ucm_event_process(event, uevent); 423 + result = ib_ucm_event_process(ctx, event, uevent); 419 424 if (result) 420 - goto done; 425 + goto err2; 421 426 422 427 uevent->ctx = ctx; 423 - uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED || 424 - event->event == IB_CM_SIDR_REQ_RECEIVED ) ? 425 - cm_id : NULL); 428 + uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL; 426 429 427 430 down(&ctx->file->mutex); 428 - 429 431 list_add_tail(&uevent->file_list, &ctx->file->events); 430 432 list_add_tail(&uevent->ctx_list, &ctx->events); 431 - 432 433 wake_up_interruptible(&ctx->file->poll_wait); 433 - 434 434 up(&ctx->file->mutex); 435 - done: 436 - ctx->error = result; 437 - ib_ucm_ctx_put(ctx); /* func reference */ 438 - return result; 435 + return 0; 436 + 437 + err2: 438 + kfree(uevent); 439 + err1: 440 + /* Destroy new cm_id's */ 441 + return (id == IB_UCM_CM_ID_INVALID); 439 442 } 440 443 441 444 static ssize_t ib_ucm_event(struct ib_ucm_file *file, ··· 472 517 goto done; 473 518 } 474 519 475 - ctx->cm_id = uevent->cm_id; 476 - ctx->cm_id->cm_handler = ib_ucm_event_handler; 477 - ctx->cm_id->context = (void *)(unsigned long)ctx->id; 520 + ctx->cm_id = uevent->cm_id; 521 + ctx->cm_id->context = ctx; 478 522 479 523 uevent->resp.id = ctx->id; 480 524 ··· 539 585 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 540 586 return -EFAULT; 541 587 588 + down(&file->mutex); 542 589 ctx = ib_ucm_ctx_alloc(file); 590 + up(&file->mutex); 543 591 if (!ctx) 544 592 return -ENOMEM; 545 593 546 - ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, 547 - (void *)(unsigned long)ctx->id); 548 - if (!ctx->cm_id) { 549 - result = -ENOMEM; 550 - goto err_cm; 594 + ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx); 595 + if (IS_ERR(ctx->cm_id)) { 596 + result = PTR_ERR(ctx->cm_id); 597 + goto err; 551 598 } 552 599 553 600 resp.id = ctx->id; 554 601 if (copy_to_user((void __user *)(unsigned long)cmd.response, 555 602 &resp, sizeof(resp))) { 556 603 result = -EFAULT; 557 - goto err_ret; 604 + goto err; 558 605 } 559 606 560 607 return 0; 561 - err_ret: 562 - ib_destroy_cm_id(ctx->cm_id); 563 - err_cm: 564 - ib_ucm_ctx_put(ctx); /* user reference */ 565 608 609 + err: 610 + ib_ucm_destroy_ctx(file, ctx->id); 566 611 return result; 567 612 } 568 613 ··· 570 617 int in_len, int out_len) 571 618 { 572 619 struct ib_ucm_destroy_id cmd; 573 - struct ib_ucm_context *ctx; 574 620 575 621 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 576 622 return -EFAULT; 577 623 578 - ctx = ib_ucm_ctx_get(cmd.id); 579 - if (!ctx) 580 - return -ENOENT; 581 - 582 - ib_ucm_ctx_put(ctx); /* user reference */ 583 - ib_ucm_ctx_put(ctx); /* func reference */ 584 - 585 - return 0; 624 + return ib_ucm_destroy_ctx(file, cmd.id); 586 625 } 587 626 588 627 static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, ··· 592 647 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 593 648 return -EFAULT; 594 649 595 - ctx = ib_ucm_ctx_get(cmd.id); 596 - if (!ctx) 597 - return -ENOENT; 598 - 599 - down(&ctx->file->mutex); 600 - if (ctx->file != file) { 601 - result = -EINVAL; 602 - goto done; 603 - } 650 + ctx = ib_ucm_ctx_get(file, cmd.id); 651 + if (IS_ERR(ctx)) 652 + return PTR_ERR(ctx); 604 653 605 654 resp.service_id = ctx->cm_id->service_id; 606 655 resp.service_mask = ctx->cm_id->service_mask; ··· 605 666 &resp, sizeof(resp))) 606 667 result = -EFAULT; 607 668 608 - done: 609 - up(&ctx->file->mutex); 610 - ib_ucm_ctx_put(ctx); /* func reference */ 669 + ib_ucm_ctx_put(ctx); 611 670 return result; 612 671 } 613 672 ··· 620 683 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 621 684 return -EFAULT; 622 685 623 - ctx = ib_ucm_ctx_get(cmd.id); 624 - if (!ctx) 625 - return -ENOENT; 686 + ctx = ib_ucm_ctx_get(file, cmd.id); 687 + if (IS_ERR(ctx)) 688 + return PTR_ERR(ctx); 626 689 627 - down(&ctx->file->mutex); 628 - if (ctx->file != file) 629 - result = -EINVAL; 630 - else 631 - result = ib_cm_listen(ctx->cm_id, cmd.service_id, 632 - cmd.service_mask); 633 - 634 - up(&ctx->file->mutex); 635 - ib_ucm_ctx_put(ctx); /* func reference */ 690 + result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask); 691 + ib_ucm_ctx_put(ctx); 636 692 return result; 637 693 } 638 694 ··· 640 710 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 641 711 return -EFAULT; 642 712 643 - ctx = ib_ucm_ctx_get(cmd.id); 644 - if (!ctx) 645 - return -ENOENT; 713 + ctx = ib_ucm_ctx_get(file, cmd.id); 714 + if (IS_ERR(ctx)) 715 + return PTR_ERR(ctx); 646 716 647 - down(&ctx->file->mutex); 648 - if (ctx->file != file) 649 - result = -EINVAL; 650 - else 651 - result = ib_cm_establish(ctx->cm_id); 652 - 653 - up(&ctx->file->mutex); 654 - ib_ucm_ctx_put(ctx); /* func reference */ 717 + result = ib_cm_establish(ctx->cm_id); 718 + ib_ucm_ctx_put(ctx); 655 719 return result; 656 720 } 657 721 ··· 692 768 return -EFAULT; 693 769 } 694 770 695 - memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid)); 696 - memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid)); 771 + memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid); 772 + memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid); 697 773 698 774 sa_path->dlid = ucm_path.dlid; 699 775 sa_path->slid = ucm_path.slid; ··· 763 839 param.max_cm_retries = cmd.max_cm_retries; 764 840 param.srq = cmd.srq; 765 841 766 - ctx = ib_ucm_ctx_get(cmd.id); 767 - if (!ctx) { 768 - result = -ENOENT; 769 - goto done; 770 - } 771 - 772 - down(&ctx->file->mutex); 773 - if (ctx->file != file) 774 - result = -EINVAL; 775 - else 842 + ctx = ib_ucm_ctx_get(file, cmd.id); 843 + if (!IS_ERR(ctx)) { 776 844 result = ib_send_cm_req(ctx->cm_id, &param); 845 + ib_ucm_ctx_put(ctx); 846 + } else 847 + result = PTR_ERR(ctx); 777 848 778 - up(&ctx->file->mutex); 779 - ib_ucm_ctx_put(ctx); /* func reference */ 780 849 done: 781 850 kfree(param.private_data); 782 851 kfree(param.primary_path); 783 852 kfree(param.alternate_path); 784 - 785 853 return result; 786 854 } 787 855 ··· 806 890 param.rnr_retry_count = cmd.rnr_retry_count; 807 891 param.srq = cmd.srq; 808 892 809 - ctx = ib_ucm_ctx_get(cmd.id); 810 - if (!ctx) { 811 - result = -ENOENT; 812 - goto done; 813 - } 814 - 815 - down(&ctx->file->mutex); 816 - if (ctx->file != file) 817 - result = -EINVAL; 818 - else 893 + ctx = ib_ucm_ctx_get(file, cmd.id); 894 + if (!IS_ERR(ctx)) { 819 895 result = ib_send_cm_rep(ctx->cm_id, &param); 896 + ib_ucm_ctx_put(ctx); 897 + } else 898 + result = PTR_ERR(ctx); 820 899 821 - up(&ctx->file->mutex); 822 - ib_ucm_ctx_put(ctx); /* func reference */ 823 - done: 824 900 kfree(param.private_data); 825 - 826 901 return result; 827 902 } 828 903 ··· 835 928 if (result) 836 929 return result; 837 930 838 - ctx = ib_ucm_ctx_get(cmd.id); 839 - if (!ctx) { 840 - result = -ENOENT; 841 - goto done; 842 - } 843 - 844 - down(&ctx->file->mutex); 845 - if (ctx->file != file) 846 - result = -EINVAL; 847 - else 931 + ctx = ib_ucm_ctx_get(file, cmd.id); 932 + if (!IS_ERR(ctx)) { 848 933 result = func(ctx->cm_id, private_data, cmd.len); 934 + ib_ucm_ctx_put(ctx); 935 + } else 936 + result = PTR_ERR(ctx); 849 937 850 - up(&ctx->file->mutex); 851 - ib_ucm_ctx_put(ctx); /* func reference */ 852 - done: 853 938 kfree(private_data); 854 - 855 939 return result; 856 940 } 857 941 ··· 893 995 if (result) 894 996 goto done; 895 997 896 - ctx = ib_ucm_ctx_get(cmd.id); 897 - if (!ctx) { 898 - result = -ENOENT; 899 - goto done; 900 - } 901 - 902 - down(&ctx->file->mutex); 903 - if (ctx->file != file) 904 - result = -EINVAL; 905 - else 906 - result = func(ctx->cm_id, cmd.status, 907 - info, cmd.info_len, 998 + ctx = ib_ucm_ctx_get(file, cmd.id); 999 + if (!IS_ERR(ctx)) { 1000 + result = func(ctx->cm_id, cmd.status, info, cmd.info_len, 908 1001 data, cmd.data_len); 1002 + ib_ucm_ctx_put(ctx); 1003 + } else 1004 + result = PTR_ERR(ctx); 909 1005 910 - up(&ctx->file->mutex); 911 - ib_ucm_ctx_put(ctx); /* func reference */ 912 1006 done: 913 1007 kfree(data); 914 1008 kfree(info); 915 - 916 1009 return result; 917 1010 } 918 1011 ··· 937 1048 if (result) 938 1049 return result; 939 1050 940 - ctx = ib_ucm_ctx_get(cmd.id); 941 - if (!ctx) { 942 - result = -ENOENT; 943 - goto done; 944 - } 1051 + ctx = ib_ucm_ctx_get(file, cmd.id); 1052 + if (!IS_ERR(ctx)) { 1053 + result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len); 1054 + ib_ucm_ctx_put(ctx); 1055 + } else 1056 + result = PTR_ERR(ctx); 945 1057 946 - down(&ctx->file->mutex); 947 - if (ctx->file != file) 948 - result = -EINVAL; 949 - else 950 - result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, 951 - data, cmd.len); 952 - 953 - up(&ctx->file->mutex); 954 - ib_ucm_ctx_put(ctx); /* func reference */ 955 - done: 956 1058 kfree(data); 957 - 958 1059 return result; 959 1060 } 960 1061 ··· 969 1090 if (result) 970 1091 goto done; 971 1092 972 - ctx = ib_ucm_ctx_get(cmd.id); 973 - if (!ctx) { 974 - result = -ENOENT; 975 - goto done; 976 - } 977 - 978 - down(&ctx->file->mutex); 979 - if (ctx->file != file) 980 - result = -EINVAL; 981 - else 1093 + ctx = ib_ucm_ctx_get(file, cmd.id); 1094 + if (!IS_ERR(ctx)) { 982 1095 result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len); 1096 + ib_ucm_ctx_put(ctx); 1097 + } else 1098 + result = PTR_ERR(ctx); 983 1099 984 - up(&ctx->file->mutex); 985 - ib_ucm_ctx_put(ctx); /* func reference */ 986 1100 done: 987 1101 kfree(data); 988 1102 kfree(path); 989 - 990 1103 return result; 991 1104 } 992 1105 ··· 1011 1140 param.max_cm_retries = cmd.max_cm_retries; 1012 1141 param.pkey = cmd.pkey; 1013 1142 1014 - ctx = ib_ucm_ctx_get(cmd.id); 1015 - if (!ctx) { 1016 - result = -ENOENT; 1017 - goto done; 1018 - } 1019 - 1020 - down(&ctx->file->mutex); 1021 - if (ctx->file != file) 1022 - result = -EINVAL; 1023 - else 1143 + ctx = ib_ucm_ctx_get(file, cmd.id); 1144 + if (!IS_ERR(ctx)) { 1024 1145 result = ib_send_cm_sidr_req(ctx->cm_id, &param); 1146 + ib_ucm_ctx_put(ctx); 1147 + } else 1148 + result = PTR_ERR(ctx); 1025 1149 1026 - up(&ctx->file->mutex); 1027 - ib_ucm_ctx_put(ctx); /* func reference */ 1028 1150 done: 1029 1151 kfree(param.private_data); 1030 1152 kfree(param.path); 1031 - 1032 1153 return result; 1033 1154 } 1034 1155 ··· 1047 1184 if (result) 1048 1185 goto done; 1049 1186 1050 - param.qp_num = cmd.qpn; 1051 - param.qkey = cmd.qkey; 1052 - param.status = cmd.status; 1053 - param.info_length = cmd.info_len; 1054 - param.private_data_len = cmd.data_len; 1187 + param.qp_num = cmd.qpn; 1188 + param.qkey = cmd.qkey; 1189 + param.status = cmd.status; 1190 + param.info_length = cmd.info_len; 1191 + param.private_data_len = cmd.data_len; 1055 1192 1056 - ctx = ib_ucm_ctx_get(cmd.id); 1057 - if (!ctx) { 1058 - result = -ENOENT; 1059 - goto done; 1060 - } 1061 - 1062 - down(&ctx->file->mutex); 1063 - if (ctx->file != file) 1064 - result = -EINVAL; 1065 - else 1193 + ctx = ib_ucm_ctx_get(file, cmd.id); 1194 + if (!IS_ERR(ctx)) { 1066 1195 result = ib_send_cm_sidr_rep(ctx->cm_id, &param); 1196 + ib_ucm_ctx_put(ctx); 1197 + } else 1198 + result = PTR_ERR(ctx); 1067 1199 1068 - up(&ctx->file->mutex); 1069 - ib_ucm_ctx_put(ctx); /* func reference */ 1070 1200 done: 1071 1201 kfree(param.private_data); 1072 1202 kfree(param.info); 1073 - 1074 1203 return result; 1075 1204 } 1076 1205 ··· 1160 1305 struct ib_ucm_context *ctx; 1161 1306 1162 1307 down(&file->mutex); 1163 - 1164 1308 while (!list_empty(&file->ctxs)) { 1165 1309 1166 1310 ctx = list_entry(file->ctxs.next, 1167 1311 struct ib_ucm_context, file_list); 1168 1312 1169 - up(&ctx->file->mutex); 1170 - ib_ucm_ctx_put(ctx); /* user reference */ 1313 + up(&file->mutex); 1314 + ib_ucm_destroy_ctx(file, ctx->id); 1171 1315 down(&file->mutex); 1172 1316 } 1173 - 1174 1317 up(&file->mutex); 1175 - 1176 1318 kfree(file); 1177 - 1178 - ucm_dbg("Deleted struct\n"); 1179 1319 return 0; 1180 1320 } 1181 1321
+3 -6
drivers/infiniband/core/ucm.h
··· 48 48 struct ib_ucm_file { 49 49 struct semaphore mutex; 50 50 struct file *filp; 51 - /* 52 - * list of pending events 53 - */ 51 + 54 52 struct list_head ctxs; /* list of active connections */ 55 53 struct list_head events; /* list of pending events */ 56 54 wait_queue_head_t poll_wait; ··· 56 58 57 59 struct ib_ucm_context { 58 60 int id; 59 - int ref; 60 - int error; 61 + wait_queue_head_t wait; 62 + atomic_t ref; 61 63 62 64 struct ib_ucm_file *file; 63 65 struct ib_cm_id *cm_id; 64 - struct semaphore mutex; 65 66 66 67 struct list_head events; /* list of pending events. */ 67 68 struct list_head file_list; /* member in file ctx list */