scst_local: Fix a race condition

Avoid that the following crash can occur:

general protection fault: 0000 [#1] PREEMPT SMP
RIP: 0010:scsi_is_host_device+0x7/0x20 [scsi_mod]
Call Trace:
 scst_process_aens+0x95/0x1d0 [scst_local]
 scst_aen_work_fn+0x6f/0x120 [scst_local]
 process_one_work+0x20b/0x6c0
 worker_thread+0x4e/0x4a0
 kthread+0x113/0x150
 ret_from_fork+0x31/0x40


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7185 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2017-05-14 18:56:09 +00:00
parent 830369e50d
commit b2b15e1d55

View File

@@ -1265,6 +1265,7 @@ static void scst_process_aens(struct scst_local_sess *sess,
__acquires(&sess->aen_lock)
{
struct scst_aen_work_item *work_item = NULL;
struct Scsi_Host *shost;
TRACE_ENTRY();
@@ -1274,7 +1275,9 @@ static void scst_process_aens(struct scst_local_sess *sess,
work_item = list_first_entry(&sess->aen_work_list,
struct scst_aen_work_item, work_list_entry);
list_del(&work_item->work_list_entry);
shost = sess->shost;
if (shost && !scsi_host_get(shost))
shost = NULL;
spin_unlock(&sess->aen_lock);
if (cleanup_only)
@@ -1283,13 +1286,17 @@ static void scst_process_aens(struct scst_local_sess *sess,
sBUG_ON(work_item->aen->event_fn != SCST_AEN_SCSI);
/* Let's always rescan */
scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
SCAN_WILD_CARD, 1);
if (shost)
scsi_scan_target(&shost->shost_gendev, 0, 0,
SCAN_WILD_CARD, 1);
done:
scst_aen_done(work_item->aen);
kfree(work_item);
if (shost)
scsi_host_put(shost);
spin_lock(&sess->aen_lock);
}
@@ -1707,12 +1714,18 @@ out:
static int scst_local_driver_remove(struct device *dev)
{
struct scst_local_sess *sess;
struct Scsi_Host *shost = NULL;
TRACE_ENTRY();
sess = to_scst_lcl_sess(dev);
scsi_remove_host(sess->shost);
scsi_host_put(sess->shost);
spin_lock(&sess->aen_lock);
swap(sess->shost, shost);
spin_unlock(&sess->aen_lock);
scsi_remove_host(shost);
scsi_host_put(shost);
TRACE_EXIT();
return 0;