Skip to content

Commit 251a152

Browse files
committed
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "Seven fixes, five in drivers. The two core changes are a trivial warning removal in scsi_scan.c and a change to rescan for capacity when a device makes a user induced (via a write to the state variable) offline->running transition to fix issues with device mapper" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: core: Fix capacity set to zero after offlinining device scsi: sr: Return correct event when media event code is 3 scsi: ibmvfc: Fix command state accounting and stale response detection scsi: core: Avoid printing an error if target_alloc() returns -ENXIO scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach() scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry() scsi: pm80xx: Fix TMF task completion race condition
2 parents 0c2e31d + f0f82e2 commit 251a152

File tree

8 files changed

+59
-32
lines changed

8 files changed

+59
-32
lines changed

drivers/scsi/device_handler/scsi_dh_rdac.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,8 @@ static int initialize_controller(struct scsi_device *sdev,
453453
if (!h->ctlr)
454454
err = SCSI_DH_RES_TEMP_UNAVAIL;
455455
else {
456-
list_add_rcu(&h->node, &h->ctlr->dh_list);
457456
h->sdev = sdev;
457+
list_add_rcu(&h->node, &h->ctlr->dh_list);
458458
}
459459
spin_unlock(&list_lock);
460460
err = SCSI_DH_OK;
@@ -778,11 +778,11 @@ static void rdac_bus_detach( struct scsi_device *sdev )
778778
spin_lock(&list_lock);
779779
if (h->ctlr) {
780780
list_del_rcu(&h->node);
781-
h->sdev = NULL;
782781
kref_put(&h->ctlr->kref, release_controller);
783782
}
784783
spin_unlock(&list_lock);
785784
sdev->handler_data = NULL;
785+
synchronize_rcu();
786786
kfree(h);
787787
}
788788

drivers/scsi/ibmvscsi/ibmvfc.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,13 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
807807
for (i = 0; i < size; ++i) {
808808
struct ibmvfc_event *evt = &pool->events[i];
809809

810+
/*
811+
* evt->active states
812+
* 1 = in flight
813+
* 0 = being completed
814+
* -1 = free/freed
815+
*/
816+
atomic_set(&evt->active, -1);
810817
atomic_set(&evt->free, 1);
811818
evt->crq.valid = 0x80;
812819
evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
@@ -1017,6 +1024,7 @@ static void ibmvfc_free_event(struct ibmvfc_event *evt)
10171024

10181025
BUG_ON(!ibmvfc_valid_event(pool, evt));
10191026
BUG_ON(atomic_inc_return(&evt->free) != 1);
1027+
BUG_ON(atomic_dec_and_test(&evt->active));
10201028

10211029
spin_lock_irqsave(&evt->queue->l_lock, flags);
10221030
list_add_tail(&evt->queue_list, &evt->queue->free);
@@ -1072,6 +1080,12 @@ static void ibmvfc_complete_purge(struct list_head *purge_list)
10721080
**/
10731081
static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
10741082
{
1083+
/*
1084+
* Anything we are failing should still be active. Otherwise, it
1085+
* implies we already got a response for the command and are doing
1086+
* something bad like double completing it.
1087+
*/
1088+
BUG_ON(!atomic_dec_and_test(&evt->active));
10751089
if (evt->cmnd) {
10761090
evt->cmnd->result = (error_code << 16);
10771091
evt->done = ibmvfc_scsi_eh_done;
@@ -1723,6 +1737,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
17231737

17241738
evt->done(evt);
17251739
} else {
1740+
atomic_set(&evt->active, 1);
17261741
spin_unlock_irqrestore(&evt->queue->l_lock, flags);
17271742
ibmvfc_trc_start(evt);
17281743
}
@@ -3251,7 +3266,7 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost,
32513266
return;
32523267
}
32533268

3254-
if (unlikely(atomic_read(&evt->free))) {
3269+
if (unlikely(atomic_dec_if_positive(&evt->active))) {
32553270
dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n",
32563271
crq->ioba);
32573272
return;
@@ -3778,7 +3793,7 @@ static void ibmvfc_handle_scrq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost
37783793
return;
37793794
}
37803795

3781-
if (unlikely(atomic_read(&evt->free))) {
3796+
if (unlikely(atomic_dec_if_positive(&evt->active))) {
37823797
dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n",
37833798
crq->ioba);
37843799
return;

drivers/scsi/ibmvscsi/ibmvfc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ struct ibmvfc_event {
745745
struct ibmvfc_target *tgt;
746746
struct scsi_cmnd *cmnd;
747747
atomic_t free;
748+
atomic_t active;
748749
union ibmvfc_iu *xfer_iu;
749750
void (*done)(struct ibmvfc_event *evt);
750751
void (*_done)(struct ibmvfc_event *evt);

drivers/scsi/megaraid/megaraid_mm.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
238238
mimd_t mimd;
239239
uint32_t adapno;
240240
int iterator;
241-
241+
bool is_found;
242242

243243
if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) {
244244
*rval = -EFAULT;
@@ -254,12 +254,16 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
254254

255255
adapter = NULL;
256256
iterator = 0;
257+
is_found = false;
257258

258259
list_for_each_entry(adapter, &adapters_list_g, list) {
259-
if (iterator++ == adapno) break;
260+
if (iterator++ == adapno) {
261+
is_found = true;
262+
break;
263+
}
260264
}
261265

262-
if (!adapter) {
266+
if (!is_found) {
263267
*rval = -ENODEV;
264268
return NULL;
265269
}
@@ -725,6 +729,7 @@ ioctl_done(uioc_t *kioc)
725729
uint32_t adapno;
726730
int iterator;
727731
mraid_mmadp_t* adapter;
732+
bool is_found;
728733

729734
/*
730735
* When the kioc returns from driver, make sure it still doesn't
@@ -747,19 +752,23 @@ ioctl_done(uioc_t *kioc)
747752
iterator = 0;
748753
adapter = NULL;
749754
adapno = kioc->adapno;
755+
is_found = false;
750756

751757
con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed "
752758
"ioctl that was timedout before\n"));
753759

754760
list_for_each_entry(adapter, &adapters_list_g, list) {
755-
if (iterator++ == adapno) break;
761+
if (iterator++ == adapno) {
762+
is_found = true;
763+
break;
764+
}
756765
}
757766

758767
kioc->timedout = 0;
759768

760-
if (adapter) {
769+
if (is_found)
761770
mraid_mm_dealloc_kioc( adapter, kioc );
762-
}
771+
763772
}
764773
else {
765774
wake_up(&wait_q);

drivers/scsi/pm8001/pm8001_sas.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -684,18 +684,22 @@ int pm8001_dev_found(struct domain_device *dev)
684684

685685
void pm8001_task_done(struct sas_task *task)
686686
{
687-
if (!del_timer(&task->slow_task->timer))
688-
return;
687+
del_timer(&task->slow_task->timer);
689688
complete(&task->slow_task->completion);
690689
}
691690

692691
static void pm8001_tmf_timedout(struct timer_list *t)
693692
{
694693
struct sas_task_slow *slow = from_timer(slow, t, timer);
695694
struct sas_task *task = slow->task;
695+
unsigned long flags;
696696

697-
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
698-
complete(&task->slow_task->completion);
697+
spin_lock_irqsave(&task->task_state_lock, flags);
698+
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
699+
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
700+
complete(&task->slow_task->completion);
701+
}
702+
spin_unlock_irqrestore(&task->task_state_lock, flags);
699703
}
700704

701705
#define PM8001_TASK_TIMEOUT 20
@@ -748,13 +752,10 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
748752
}
749753
res = -TMF_RESP_FUNC_FAILED;
750754
/* Even TMF timed out, return direct. */
751-
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
752-
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
753-
pm8001_dbg(pm8001_ha, FAIL,
754-
"TMF task[%x]timeout.\n",
755-
tmf->tmf);
756-
goto ex_err;
757-
}
755+
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
756+
pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n",
757+
tmf->tmf);
758+
goto ex_err;
758759
}
759760

760761
if (task->task_status.resp == SAS_TASK_COMPLETE &&
@@ -834,12 +835,9 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
834835
wait_for_completion(&task->slow_task->completion);
835836
res = TMF_RESP_FUNC_FAILED;
836837
/* Even TMF timed out, return direct. */
837-
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
838-
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
839-
pm8001_dbg(pm8001_ha, FAIL,
840-
"TMF task timeout.\n");
841-
goto ex_err;
842-
}
838+
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
839+
pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
840+
goto ex_err;
843841
}
844842

845843
if (task->task_status.resp == SAS_TASK_COMPLETE &&

drivers/scsi/scsi_scan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
475475
error = shost->hostt->target_alloc(starget);
476476

477477
if(error) {
478-
dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
478+
if (error != -ENXIO)
479+
dev_err(dev, "target allocation failed, error %d\n", error);
479480
/* don't want scsi_target_reap to do the final
480481
* put because it will be under the host lock */
481482
scsi_target_destroy(starget);

drivers/scsi/scsi_sysfs.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -807,11 +807,14 @@ store_state_field(struct device *dev, struct device_attribute *attr,
807807
mutex_lock(&sdev->state_mutex);
808808
ret = scsi_device_set_state(sdev, state);
809809
/*
810-
* If the device state changes to SDEV_RUNNING, we need to run
811-
* the queue to avoid I/O hang.
810+
* If the device state changes to SDEV_RUNNING, we need to
811+
* rescan the device to revalidate it, and run the queue to
812+
* avoid I/O hang.
812813
*/
813-
if (ret == 0 && state == SDEV_RUNNING)
814+
if (ret == 0 && state == SDEV_RUNNING) {
815+
scsi_rescan_device(dev);
814816
blk_mq_run_hw_queues(sdev->request_queue, true);
817+
}
815818
mutex_unlock(&sdev->state_mutex);
816819

817820
return ret == 0 ? count : -EINVAL;

drivers/scsi/sr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ static unsigned int sr_get_events(struct scsi_device *sdev)
221221
else if (med->media_event_code == 2)
222222
return DISK_EVENT_MEDIA_CHANGE;
223223
else if (med->media_event_code == 3)
224-
return DISK_EVENT_EJECT_REQUEST;
224+
return DISK_EVENT_MEDIA_CHANGE;
225225
return 0;
226226
}
227227

0 commit comments

Comments
 (0)