Commit f8e24eab authored by Nicholas Bellinger's avatar Nicholas Bellinger Committed by Greg Kroah-Hartman

target/pscsi: Fix TYPE_TAPE + TYPE_MEDIMUM_CHANGER export

commit a04e54f2 upstream.

The following fixes a divide by zero OOPs with TYPE_TAPE
due to pscsi_tape_read_blocksize() failing causing a zero
sd->sector_size being propigated up via dev_attrib.hw_block_size.

It also fixes another long-standing bug where TYPE_TAPE and
TYPE_MEDIMUM_CHANGER where using pscsi_create_type_other(),
which does not call scsi_device_get() to take the device
reference.  Instead, rename pscsi_create_type_rom() to
pscsi_create_type_nondisk() and use it for all cases.

Finally, also drop a dump_stack() in pscsi_get_blocks() for
non TYPE_DISK, which in modern target-core can get invoked
via target_sense_desc_format() during CHECK_CONDITION.
Reported-by: default avatarMalcolm Haak <insanemal@gmail.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ad516641
...@@ -154,7 +154,7 @@ static void pscsi_tape_read_blocksize(struct se_device *dev, ...@@ -154,7 +154,7 @@ static void pscsi_tape_read_blocksize(struct se_device *dev,
buf = kzalloc(12, GFP_KERNEL); buf = kzalloc(12, GFP_KERNEL);
if (!buf) if (!buf)
return; goto out_free;
memset(cdb, 0, MAX_COMMAND_SIZE); memset(cdb, 0, MAX_COMMAND_SIZE);
cdb[0] = MODE_SENSE; cdb[0] = MODE_SENSE;
...@@ -169,9 +169,10 @@ static void pscsi_tape_read_blocksize(struct se_device *dev, ...@@ -169,9 +169,10 @@ static void pscsi_tape_read_blocksize(struct se_device *dev,
* If MODE_SENSE still returns zero, set the default value to 1024. * If MODE_SENSE still returns zero, set the default value to 1024.
*/ */
sdev->sector_size = (buf[9] << 16) | (buf[10] << 8) | (buf[11]); sdev->sector_size = (buf[9] << 16) | (buf[10] << 8) | (buf[11]);
out_free:
if (!sdev->sector_size) if (!sdev->sector_size)
sdev->sector_size = 1024; sdev->sector_size = 1024;
out_free:
kfree(buf); kfree(buf);
} }
...@@ -314,9 +315,10 @@ static int pscsi_add_device_to_list(struct se_device *dev, ...@@ -314,9 +315,10 @@ static int pscsi_add_device_to_list(struct se_device *dev,
sd->lun, sd->queue_depth); sd->lun, sd->queue_depth);
} }
dev->dev_attrib.hw_block_size = sd->sector_size; dev->dev_attrib.hw_block_size =
min_not_zero((int)sd->sector_size, 512);
dev->dev_attrib.hw_max_sectors = dev->dev_attrib.hw_max_sectors =
min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q)); min_not_zero(sd->host->max_sectors, queue_max_hw_sectors(q));
dev->dev_attrib.hw_queue_depth = sd->queue_depth; dev->dev_attrib.hw_queue_depth = sd->queue_depth;
/* /*
...@@ -339,8 +341,10 @@ static int pscsi_add_device_to_list(struct se_device *dev, ...@@ -339,8 +341,10 @@ static int pscsi_add_device_to_list(struct se_device *dev,
/* /*
* For TYPE_TAPE, attempt to determine blocksize with MODE_SENSE. * For TYPE_TAPE, attempt to determine blocksize with MODE_SENSE.
*/ */
if (sd->type == TYPE_TAPE) if (sd->type == TYPE_TAPE) {
pscsi_tape_read_blocksize(dev, sd); pscsi_tape_read_blocksize(dev, sd);
dev->dev_attrib.hw_block_size = sd->sector_size;
}
return 0; return 0;
} }
...@@ -406,7 +410,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) ...@@ -406,7 +410,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
/* /*
* Called with struct Scsi_Host->host_lock called. * Called with struct Scsi_Host->host_lock called.
*/ */
static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) static int pscsi_create_type_nondisk(struct se_device *dev, struct scsi_device *sd)
__releases(sh->host_lock) __releases(sh->host_lock)
{ {
struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
...@@ -433,28 +437,6 @@ static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) ...@@ -433,28 +437,6 @@ static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd)
return 0; return 0;
} }
/*
* Called with struct Scsi_Host->host_lock called.
*/
static int pscsi_create_type_other(struct se_device *dev,
struct scsi_device *sd)
__releases(sh->host_lock)
{
struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
struct Scsi_Host *sh = sd->host;
int ret;
spin_unlock_irq(sh->host_lock);
ret = pscsi_add_device_to_list(dev, sd);
if (ret)
return ret;
pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%llu\n",
phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
sd->channel, sd->id, sd->lun);
return 0;
}
static int pscsi_configure_device(struct se_device *dev) static int pscsi_configure_device(struct se_device *dev)
{ {
struct se_hba *hba = dev->se_hba; struct se_hba *hba = dev->se_hba;
...@@ -542,11 +524,8 @@ static int pscsi_configure_device(struct se_device *dev) ...@@ -542,11 +524,8 @@ static int pscsi_configure_device(struct se_device *dev)
case TYPE_DISK: case TYPE_DISK:
ret = pscsi_create_type_disk(dev, sd); ret = pscsi_create_type_disk(dev, sd);
break; break;
case TYPE_ROM:
ret = pscsi_create_type_rom(dev, sd);
break;
default: default:
ret = pscsi_create_type_other(dev, sd); ret = pscsi_create_type_nondisk(dev, sd);
break; break;
} }
...@@ -611,7 +590,6 @@ static void pscsi_free_device(struct se_device *dev) ...@@ -611,7 +590,6 @@ static void pscsi_free_device(struct se_device *dev)
else if (pdv->pdv_lld_host) else if (pdv->pdv_lld_host)
scsi_host_put(pdv->pdv_lld_host); scsi_host_put(pdv->pdv_lld_host);
if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM))
scsi_device_put(sd); scsi_device_put(sd);
pdv->pdv_sd = NULL; pdv->pdv_sd = NULL;
...@@ -1069,7 +1047,6 @@ static sector_t pscsi_get_blocks(struct se_device *dev) ...@@ -1069,7 +1047,6 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
if (pdv->pdv_bd && pdv->pdv_bd->bd_part) if (pdv->pdv_bd && pdv->pdv_bd->bd_part)
return pdv->pdv_bd->bd_part->nr_sects; return pdv->pdv_bd->bd_part->nr_sects;
dump_stack();
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment