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