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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
"Eight patches which looks like quite a large core change, but most of
the diffstat is reverting the attempt to rejig reference counting
introduced in the last merge window which caused issues with device
and module removal.

Of the remaining four patches, only the fix use-after-free is
substantial"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
scsi: mpt3sas: Fix use-after-free warning
scsi: core: Fix a use-after-free
scsi: core: Revert "Make sure that targets outlive devices"
scsi: core: Revert "Make sure that hosts outlive targets"
scsi: core: Revert "Simplify LLD module reference counting"
scsi: core: Revert "Call blk_mq_free_tag_set() earlier"
scsi: lpfc: Add missing destroy_workqueue() in error path
scsi: lpfc: Return DID_TRANSPORT_DISRUPTED instead of DID_REQUEUE

+47 -56
+15 -13
drivers/scsi/hosts.c
··· 182 182 mutex_unlock(&shost->scan_mutex); 183 183 scsi_proc_host_rm(shost); 184 184 185 + /* 186 + * New SCSI devices cannot be attached anymore because of the SCSI host 187 + * state so drop the tag set refcnt. Wait until the tag set refcnt drops 188 + * to zero because .exit_cmd_priv implementations may need the host 189 + * pointer. 190 + */ 191 + kref_put(&shost->tagset_refcnt, scsi_mq_free_tags); 192 + wait_for_completion(&shost->tagset_freed); 193 + 185 194 spin_lock_irqsave(shost->host_lock, flags); 186 195 if (scsi_host_set_state(shost, SHOST_DEL)) 187 196 BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); ··· 199 190 transport_unregister_device(&shost->shost_gendev); 200 191 device_unregister(&shost->shost_dev); 201 192 device_del(&shost->shost_gendev); 202 - 203 - /* 204 - * After scsi_remove_host() has returned the scsi LLD module can be 205 - * unloaded and/or the host resources can be released. Hence wait until 206 - * the dependent SCSI targets and devices are gone before returning. 207 - */ 208 - wait_event(shost->targets_wq, atomic_read(&shost->target_count) == 0); 209 - 210 - scsi_mq_destroy_tags(shost); 211 193 } 212 194 EXPORT_SYMBOL(scsi_remove_host); 213 195 ··· 253 253 error = scsi_mq_setup_tags(shost); 254 254 if (error) 255 255 goto fail; 256 + 257 + kref_init(&shost->tagset_refcnt); 258 + init_completion(&shost->tagset_freed); 256 259 257 260 /* 258 261 * Increase usage count temporarily here so that calling ··· 312 309 return error; 313 310 314 311 /* 315 - * Any resources associated with the SCSI host in this function except 316 - * the tag set will be freed by scsi_host_dev_release(). 312 + * Any host allocation in this function will be freed in 313 + * scsi_host_dev_release(). 317 314 */ 318 315 out_del_dev: 319 316 device_del(&shost->shost_dev); ··· 329 326 pm_runtime_disable(&shost->shost_gendev); 330 327 pm_runtime_set_suspended(&shost->shost_gendev); 331 328 pm_runtime_put_noidle(&shost->shost_gendev); 332 - scsi_mq_destroy_tags(shost); 329 + kref_put(&shost->tagset_refcnt, scsi_mq_free_tags); 333 330 fail: 334 331 return error; 335 332 } ··· 409 406 INIT_LIST_HEAD(&shost->starved_list); 410 407 init_waitqueue_head(&shost->host_wait); 411 408 mutex_init(&shost->scan_mutex); 412 - init_waitqueue_head(&shost->targets_wq); 413 409 414 410 index = ida_alloc(&host_index_ida, GFP_KERNEL); 415 411 if (index < 0) {
+4 -1
drivers/scsi/lpfc/lpfc_init.c
··· 8053 8053 /* Allocate device driver memory */ 8054 8054 rc = lpfc_mem_alloc(phba, SGL_ALIGN_SZ); 8055 8055 if (rc) 8056 - return -ENOMEM; 8056 + goto out_destroy_workqueue; 8057 8057 8058 8058 /* IF Type 2 ports get initialized now. */ 8059 8059 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >= ··· 8481 8481 lpfc_destroy_bootstrap_mbox(phba); 8482 8482 out_free_mem: 8483 8483 lpfc_mem_free(phba); 8484 + out_destroy_workqueue: 8485 + destroy_workqueue(phba->wq); 8486 + phba->wq = NULL; 8484 8487 return rc; 8485 8488 } 8486 8489
+2 -2
drivers/scsi/lpfc/lpfc_scsi.c
··· 4272 4272 lpfc_cmd->result == IOERR_ABORT_REQUESTED || 4273 4273 lpfc_cmd->result == IOERR_RPI_SUSPENDED || 4274 4274 lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) { 4275 - cmd->result = DID_REQUEUE << 16; 4275 + cmd->result = DID_TRANSPORT_DISRUPTED << 16; 4276 4276 break; 4277 4277 } 4278 4278 if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || ··· 4562 4562 lpfc_cmd->result == IOERR_NO_RESOURCES || 4563 4563 lpfc_cmd->result == IOERR_ABORT_REQUESTED || 4564 4564 lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) { 4565 - cmd->result = DID_REQUEUE << 16; 4565 + cmd->result = DID_TRANSPORT_DISRUPTED << 16; 4566 4566 break; 4567 4567 } 4568 4568 if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
+1 -1
drivers/scsi/mpt3sas/mpt3sas_scsih.c
··· 3670 3670 fw_event = list_first_entry(&ioc->fw_event_list, 3671 3671 struct fw_event_work, list); 3672 3672 list_del_init(&fw_event->list); 3673 + fw_event_work_put(fw_event); 3673 3674 } 3674 3675 spin_unlock_irqrestore(&ioc->fw_event_lock, flags); 3675 3676 ··· 3752 3751 if (cancel_work_sync(&fw_event->work)) 3753 3752 fw_event_work_put(fw_event); 3754 3753 3755 - fw_event_work_put(fw_event); 3756 3754 } 3757 3755 ioc->fw_events_cleanup = 0; 3758 3756 }
+3 -6
drivers/scsi/scsi.c
··· 586 586 */ 587 587 void scsi_device_put(struct scsi_device *sdev) 588 588 { 589 - /* 590 - * Decreasing the module reference count before the device reference 591 - * count is safe since scsi_remove_host() only returns after all 592 - * devices have been removed. 593 - */ 594 - module_put(sdev->host->hostt->module); 589 + struct module *mod = sdev->host->hostt->module; 590 + 595 591 put_device(&sdev->sdev_gendev); 592 + module_put(mod); 596 593 } 597 594 EXPORT_SYMBOL(scsi_device_put); 598 595
+5 -1
drivers/scsi/scsi_lib.c
··· 1983 1983 return blk_mq_alloc_tag_set(tag_set); 1984 1984 } 1985 1985 1986 - void scsi_mq_destroy_tags(struct Scsi_Host *shost) 1986 + void scsi_mq_free_tags(struct kref *kref) 1987 1987 { 1988 + struct Scsi_Host *shost = container_of(kref, typeof(*shost), 1989 + tagset_refcnt); 1990 + 1988 1991 blk_mq_free_tag_set(&shost->tag_set); 1992 + complete(&shost->tagset_freed); 1989 1993 } 1990 1994 1991 1995 /**
+1 -1
drivers/scsi/scsi_priv.h
··· 94 94 extern void scsi_requeue_run_queue(struct work_struct *work); 95 95 extern void scsi_start_queue(struct scsi_device *sdev); 96 96 extern int scsi_mq_setup_tags(struct Scsi_Host *shost); 97 - extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); 97 + extern void scsi_mq_free_tags(struct kref *kref); 98 98 extern void scsi_exit_queue(void); 99 99 extern void scsi_evt_thread(struct work_struct *work); 100 100
+1 -9
drivers/scsi/scsi_scan.c
··· 340 340 kfree(sdev); 341 341 goto out; 342 342 } 343 + kref_get(&sdev->host->tagset_refcnt); 343 344 sdev->request_queue = q; 344 345 q->queuedata = sdev; 345 346 __scsi_init_queue(sdev->host, q); ··· 407 406 static void scsi_target_dev_release(struct device *dev) 408 407 { 409 408 struct device *parent = dev->parent; 410 - struct Scsi_Host *shost = dev_to_shost(parent); 411 409 struct scsi_target *starget = to_scsi_target(dev); 412 410 413 411 kfree(starget); 414 - 415 - if (atomic_dec_return(&shost->target_count) == 0) 416 - wake_up(&shost->targets_wq); 417 - 418 412 put_device(parent); 419 413 } 420 414 ··· 522 526 starget->state = STARGET_CREATED; 523 527 starget->scsi_level = SCSI_2; 524 528 starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED; 525 - init_waitqueue_head(&starget->sdev_wq); 526 - 527 - atomic_inc(&shost->target_count); 528 - 529 529 retry: 530 530 spin_lock_irqsave(shost->host_lock, flags); 531 531
+13 -17
drivers/scsi/scsi_sysfs.c
··· 443 443 444 444 static void scsi_device_dev_release_usercontext(struct work_struct *work) 445 445 { 446 - struct scsi_device *sdev = container_of(work, struct scsi_device, 447 - ew.work); 448 - struct scsi_target *starget = sdev->sdev_target; 446 + struct scsi_device *sdev; 449 447 struct device *parent; 450 448 struct list_head *this, *tmp; 451 449 struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL; 452 450 struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL; 453 451 struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL; 454 452 unsigned long flags; 453 + struct module *mod; 454 + 455 + sdev = container_of(work, struct scsi_device, ew.work); 456 + 457 + mod = sdev->host->hostt->module; 455 458 456 459 scsi_dh_release_device(sdev); 457 460 ··· 516 513 kfree(sdev->inquiry); 517 514 kfree(sdev); 518 515 519 - if (starget && atomic_dec_return(&starget->sdev_count) == 0) 520 - wake_up(&starget->sdev_wq); 521 - 522 516 if (parent) 523 517 put_device(parent); 518 + module_put(mod); 524 519 } 525 520 526 521 static void scsi_device_dev_release(struct device *dev) 527 522 { 528 523 struct scsi_device *sdp = to_scsi_device(dev); 524 + 525 + /* Set module pointer as NULL in case of module unloading */ 526 + if (!try_module_get(sdp->host->hostt->module)) 527 + sdp->host->hostt->module = NULL; 528 + 529 529 execute_in_process_context(scsi_device_dev_release_usercontext, 530 530 &sdp->ew); 531 531 } ··· 1476 1470 mutex_unlock(&sdev->state_mutex); 1477 1471 1478 1472 blk_mq_destroy_queue(sdev->request_queue); 1473 + kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags); 1479 1474 cancel_work_sync(&sdev->requeue_work); 1480 1475 1481 1476 if (sdev->host->hostt->slave_destroy) ··· 1536 1529 goto restart; 1537 1530 } 1538 1531 spin_unlock_irqrestore(shost->host_lock, flags); 1539 - 1540 - /* 1541 - * After scsi_remove_target() returns its caller can remove resources 1542 - * associated with @starget, e.g. an rport or session. Wait until all 1543 - * devices associated with @starget have been removed to prevent that 1544 - * a SCSI error handling callback function triggers a use-after-free. 1545 - */ 1546 - wait_event(starget->sdev_wq, atomic_read(&starget->sdev_count) == 0); 1547 1532 } 1548 1533 1549 1534 /** ··· 1646 1647 list_add_tail(&sdev->same_target_siblings, &starget->devices); 1647 1648 list_add_tail(&sdev->siblings, &shost->__devices); 1648 1649 spin_unlock_irqrestore(shost->host_lock, flags); 1649 - 1650 - atomic_inc(&starget->sdev_count); 1651 - 1652 1650 /* 1653 1651 * device can now only be removed via __scsi_remove_device() so hold 1654 1652 * the target. Target will be held in CREATED state until something
-2
include/scsi/scsi_device.h
··· 309 309 struct list_head devices; 310 310 struct device dev; 311 311 struct kref reap_ref; /* last put renders target invisible */ 312 - atomic_t sdev_count; 313 - wait_queue_head_t sdev_wq; 314 312 unsigned int channel; 315 313 unsigned int id; /* target id ... replace 316 314 * scsi_device.id eventually */
+2 -3
include/scsi/scsi_host.h
··· 557 557 struct scsi_host_template *hostt; 558 558 struct scsi_transport_template *transportt; 559 559 560 + struct kref tagset_refcnt; 561 + struct completion tagset_freed; 560 562 /* Area to keep a shared tag map */ 561 563 struct blk_mq_tag_set tag_set; 562 564 ··· 691 689 692 690 /* ldm bits */ 693 691 struct device shost_gendev, shost_dev; 694 - 695 - atomic_t target_count; 696 - wait_queue_head_t targets_wq; 697 692 698 693 /* 699 694 * Points to the transport data (if any) which is allocated