Skip to content

Commit f2b8504

Browse files
Ming Leimartinkpetersen
authored andcommitted
scsi: core: Put LLD module refcnt after SCSI device is released
SCSI host release is triggered when SCSI device is freed. We have to make sure that the low-level device driver module won't be unloaded before SCSI host instance is released because shost->hostt is required in the release handler. Make sure to put LLD module refcnt after SCSI device is released. Fixes a kernel panic of 'BUG: unable to handle page fault for address' reported by Changhui and Yi. Link: https://lore.kernel.org/r/[email protected] Cc: Greg Kroah-Hartman <[email protected]> Reported-by: Changhui Zhong <[email protected]> Reported-by: Yi Zhang <[email protected]> Tested-by: Yi Zhang <[email protected]> Signed-off-by: Ming Lei <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 6fd13d6 commit f2b8504

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

drivers/scsi/scsi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,10 @@ EXPORT_SYMBOL(scsi_device_get);
553553
*/
554554
void scsi_device_put(struct scsi_device *sdev)
555555
{
556-
module_put(sdev->host->hostt->module);
556+
struct module *mod = sdev->host->hostt->module;
557+
557558
put_device(&sdev->sdev_gendev);
559+
module_put(mod);
558560
}
559561
EXPORT_SYMBOL(scsi_device_put);
560562

drivers/scsi/scsi_sysfs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,12 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
449449
struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
450450
struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
451451
unsigned long flags;
452+
struct module *mod;
452453

453454
sdev = container_of(work, struct scsi_device, ew.work);
454455

456+
mod = sdev->host->hostt->module;
457+
455458
scsi_dh_release_device(sdev);
456459

457460
parent = sdev->sdev_gendev.parent;
@@ -502,11 +505,17 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
502505

503506
if (parent)
504507
put_device(parent);
508+
module_put(mod);
505509
}
506510

507511
static void scsi_device_dev_release(struct device *dev)
508512
{
509513
struct scsi_device *sdp = to_scsi_device(dev);
514+
515+
/* Set module pointer as NULL in case of module unloading */
516+
if (!try_module_get(sdp->host->hostt->module))
517+
sdp->host->hostt->module = NULL;
518+
510519
execute_in_process_context(scsi_device_dev_release_usercontext,
511520
&sdp->ew);
512521
}

0 commit comments

Comments
 (0)