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

scsi: iscsi: Rel ref after iscsi_lookup_endpoint()

Subsequent commits allow the kernel to do ep_disconnect. In that case we
will have to get a proper refcount on the ep so one thread does not delete
it from under another.

Link: https://lore.kernel.org/r/20210525181821.7617-7-michael.christie@oracle.com
Reviewed-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Mike Christie and committed by
Martin K. Petersen
9e5fe170 b25b957d

+75 -32
+1
drivers/infiniband/ulp/iser/iscsi_iser.c
··· 506 506 iser_conn->iscsi_conn = conn; 507 507 508 508 out: 509 + iscsi_put_endpoint(ep); 509 510 mutex_unlock(&iser_conn->state_mutex); 510 511 return error; 511 512 }
+13 -6
drivers/scsi/be2iscsi/be_iscsi.c
··· 182 182 struct beiscsi_endpoint *beiscsi_ep; 183 183 struct iscsi_endpoint *ep; 184 184 uint16_t cri_index; 185 + int rc = 0; 185 186 186 187 ep = iscsi_lookup_endpoint(transport_fd); 187 188 if (!ep) ··· 190 189 191 190 beiscsi_ep = ep->dd_data; 192 191 193 - if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) 194 - return -EINVAL; 192 + if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) { 193 + rc = -EINVAL; 194 + goto put_ep; 195 + } 195 196 196 197 if (beiscsi_ep->phba != phba) { 197 198 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 198 199 "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n", 199 200 beiscsi_ep->phba, phba); 200 - 201 - return -EEXIST; 201 + rc = -EEXIST; 202 + goto put_ep; 202 203 } 203 204 cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); 204 205 if (phba->conn_table[cri_index]) { ··· 212 209 beiscsi_ep->ep_cid, 213 210 beiscsi_conn, 214 211 phba->conn_table[cri_index]); 215 - return -EINVAL; 212 + rc = -EINVAL; 213 + goto put_ep; 216 214 } 217 215 } 218 216 ··· 230 226 "BS_%d : cid %d phba->conn_table[%u]=%p\n", 231 227 beiscsi_ep->ep_cid, cri_index, beiscsi_conn); 232 228 phba->conn_table[cri_index] = beiscsi_conn; 233 - return 0; 229 + 230 + put_ep: 231 + iscsi_put_endpoint(ep); 232 + return rc; 234 233 } 235 234 236 235 static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
+16 -7
drivers/scsi/bnx2i/bnx2i_iscsi.c
··· 1420 1420 * Forcefully terminate all in progress connection recovery at the 1421 1421 * earliest, either in bind(), send_pdu(LOGIN), or conn_start() 1422 1422 */ 1423 - if (bnx2i_adapter_ready(hba)) 1424 - return -EIO; 1423 + if (bnx2i_adapter_ready(hba)) { 1424 + ret_code = -EIO; 1425 + goto put_ep; 1426 + } 1425 1427 1426 1428 bnx2i_ep = ep->dd_data; 1427 1429 if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) || 1428 - (bnx2i_ep->state == EP_STATE_TCP_RST_RCVD)) 1430 + (bnx2i_ep->state == EP_STATE_TCP_RST_RCVD)) { 1429 1431 /* Peer disconnect via' FIN or RST */ 1430 - return -EINVAL; 1432 + ret_code = -EINVAL; 1433 + goto put_ep; 1434 + } 1431 1435 1432 - if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) 1433 - return -EINVAL; 1436 + if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) { 1437 + ret_code = -EINVAL; 1438 + goto put_ep; 1439 + } 1434 1440 1435 1441 if (bnx2i_ep->hba != hba) { 1436 1442 /* Error - TCP connection does not belong to this device ··· 1447 1441 iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data, 1448 1442 "belong to hba (%s)\n", 1449 1443 hba->netdev->name); 1450 - return -EEXIST; 1444 + ret_code = -EEXIST; 1445 + goto put_ep; 1451 1446 } 1452 1447 bnx2i_ep->conn = bnx2i_conn; 1453 1448 bnx2i_conn->ep = bnx2i_ep; ··· 1465 1458 bnx2i_put_rq_buf(bnx2i_conn, 0); 1466 1459 1467 1460 bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE); 1461 + put_ep: 1462 + iscsi_put_endpoint(ep); 1468 1463 return ret_code; 1469 1464 } 1470 1465
+8 -4
drivers/scsi/cxgbi/libcxgbi.c
··· 2690 2690 err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, 2691 2691 ppm->tformat.pgsz_idx_dflt); 2692 2692 if (err < 0) 2693 - return err; 2693 + goto put_ep; 2694 2694 2695 2695 err = iscsi_conn_bind(cls_session, cls_conn, is_leading); 2696 - if (err) 2697 - return -EINVAL; 2696 + if (err) { 2697 + err = -EINVAL; 2698 + goto put_ep; 2699 + } 2698 2700 2699 2701 /* calculate the tag idx bits needed for this conn based on cmds_max */ 2700 2702 cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1; ··· 2717 2715 /* init recv engine */ 2718 2716 iscsi_tcp_hdr_recv_prep(tcp_conn); 2719 2717 2720 - return 0; 2718 + put_ep: 2719 + iscsi_put_endpoint(ep); 2720 + return err; 2721 2721 } 2722 2722 EXPORT_SYMBOL_GPL(cxgbi_bind_conn); 2723 2723
+18 -7
drivers/scsi/qedi/qedi_iscsi.c
··· 377 377 struct qedi_ctx *qedi = iscsi_host_priv(shost); 378 378 struct qedi_endpoint *qedi_ep; 379 379 struct iscsi_endpoint *ep; 380 + int rc = 0; 380 381 381 382 ep = iscsi_lookup_endpoint(transport_fd); 382 383 if (!ep) ··· 385 384 386 385 qedi_ep = ep->dd_data; 387 386 if ((qedi_ep->state == EP_STATE_TCP_FIN_RCVD) || 388 - (qedi_ep->state == EP_STATE_TCP_RST_RCVD)) 389 - return -EINVAL; 387 + (qedi_ep->state == EP_STATE_TCP_RST_RCVD)) { 388 + rc = -EINVAL; 389 + goto put_ep; 390 + } 390 391 391 - if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) 392 - return -EINVAL; 392 + if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) { 393 + rc = -EINVAL; 394 + goto put_ep; 395 + } 396 + 393 397 394 398 qedi_ep->conn = qedi_conn; 395 399 qedi_conn->ep = qedi_ep; ··· 404 398 qedi_conn->cmd_cleanup_req = 0; 405 399 qedi_conn->cmd_cleanup_cmpl = 0; 406 400 407 - if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) 408 - return -EINVAL; 401 + if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) { 402 + rc = -EINVAL; 403 + goto put_ep; 404 + } 405 + 409 406 410 407 spin_lock_init(&qedi_conn->tmf_work_lock); 411 408 INIT_LIST_HEAD(&qedi_conn->tmf_work_list); 412 409 init_waitqueue_head(&qedi_conn->wait_queue); 413 - return 0; 410 + put_ep: 411 + iscsi_put_endpoint(ep); 412 + return rc; 414 413 } 415 414 416 415 static int qedi_iscsi_update_conn(struct qedi_ctx *qedi,
+1
drivers/scsi/qla4xxx/ql4_os.c
··· 3235 3235 conn = cls_conn->dd_data; 3236 3236 qla_conn = conn->dd_data; 3237 3237 qla_conn->qla_ep = ep->dd_data; 3238 + iscsi_put_endpoint(ep); 3238 3239 return 0; 3239 3240 } 3240 3241
+17 -8
drivers/scsi/scsi_transport_iscsi.c
··· 266 266 } 267 267 EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint); 268 268 269 + void iscsi_put_endpoint(struct iscsi_endpoint *ep) 270 + { 271 + put_device(&ep->dev); 272 + } 273 + EXPORT_SYMBOL_GPL(iscsi_put_endpoint); 274 + 275 + /** 276 + * iscsi_lookup_endpoint - get ep from handle 277 + * @handle: endpoint handle 278 + * 279 + * Caller must do a iscsi_put_endpoint. 280 + */ 269 281 struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle) 270 282 { 271 - struct iscsi_endpoint *ep; 272 283 struct device *dev; 273 284 274 285 dev = class_find_device(&iscsi_endpoint_class, NULL, &handle, ··· 287 276 if (!dev) 288 277 return NULL; 289 278 290 - ep = iscsi_dev_to_endpoint(dev); 291 - /* 292 - * we can drop this now because the interface will prevent 293 - * removals and lookups from racing. 294 - */ 295 - put_device(dev); 296 - return ep; 279 + return iscsi_dev_to_endpoint(dev); 297 280 } 298 281 EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint); 299 282 ··· 2995 2990 } 2996 2991 2997 2992 transport->ep_disconnect(ep); 2993 + iscsi_put_endpoint(ep); 2998 2994 return 0; 2999 2995 } 3000 2996 ··· 3021 3015 3022 3016 ev->r.retcode = transport->ep_poll(ep, 3023 3017 ev->u.ep_poll.timeout_ms); 3018 + iscsi_put_endpoint(ep); 3024 3019 break; 3025 3020 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 3026 3021 rc = iscsi_if_ep_disconnect(transport, ··· 3705 3698 ev->u.c_bound_session.initial_cmdsn, 3706 3699 ev->u.c_bound_session.cmds_max, 3707 3700 ev->u.c_bound_session.queue_depth); 3701 + iscsi_put_endpoint(ep); 3708 3702 break; 3709 3703 case ISCSI_UEVENT_DESTROY_SESSION: 3710 3704 session = iscsi_session_lookup(ev->u.d_session.sid); ··· 3777 3769 mutex_lock(&conn->ep_mutex); 3778 3770 conn->ep = ep; 3779 3771 mutex_unlock(&conn->ep_mutex); 3772 + iscsi_put_endpoint(ep); 3780 3773 } else 3781 3774 iscsi_cls_conn_printk(KERN_ERR, conn, 3782 3775 "Could not set ep conn "
+1
include/scsi/scsi_transport_iscsi.h
··· 442 442 extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size); 443 443 extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); 444 444 extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); 445 + extern void iscsi_put_endpoint(struct iscsi_endpoint *ep); 445 446 extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd); 446 447 extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost, 447 448 struct iscsi_transport *t,