aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/target_core_device.c')
-rw-r--r--drivers/target/target_core_device.c131
1 files changed, 90 insertions, 41 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 0c5992f0d946..aa6267746383 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -72,7 +72,7 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
}
spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
- se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+ se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
if (se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
struct se_dev_entry *deve = se_cmd->se_deve;
@@ -159,13 +159,8 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
dev->read_bytes += se_cmd->data_length;
spin_unlock_irqrestore(&dev->stats_lock, flags);
- /*
- * Add the iscsi_cmd_t to the struct se_lun's cmd list. This list is used
- * for tracking state of struct se_cmds during LUN shutdown events.
- */
spin_lock_irqsave(&se_lun->lun_cmd_lock, flags);
list_add_tail(&se_cmd->se_lun_node, &se_lun->lun_cmd_list);
- atomic_set(&se_cmd->transport_lun_active, 1);
spin_unlock_irqrestore(&se_lun->lun_cmd_lock, flags);
return 0;
@@ -187,7 +182,7 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
}
spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
- se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+ se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
deve = se_cmd->se_deve;
if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
@@ -245,7 +240,7 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
spin_lock_irq(&nacl->device_list_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
- deve = &nacl->device_list[i];
+ deve = nacl->device_list[i];
if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
continue;
@@ -291,7 +286,7 @@ int core_free_device_list_for_node(
spin_lock_irq(&nacl->device_list_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
- deve = &nacl->device_list[i];
+ deve = nacl->device_list[i];
if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
continue;
@@ -311,7 +306,7 @@ int core_free_device_list_for_node(
}
spin_unlock_irq(&nacl->device_list_lock);
- kfree(nacl->device_list);
+ array_free(nacl->device_list, TRANSPORT_MAX_LUNS_PER_TPG);
nacl->device_list = NULL;
return 0;
@@ -320,11 +315,12 @@ int core_free_device_list_for_node(
void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
{
struct se_dev_entry *deve;
+ unsigned long flags;
- spin_lock_irq(&se_nacl->device_list_lock);
- deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
+ spin_lock_irqsave(&se_nacl->device_list_lock, flags);
+ deve = se_nacl->device_list[se_cmd->orig_fe_lun];
deve->deve_cmds--;
- spin_unlock_irq(&se_nacl->device_list_lock);
+ spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
}
void core_update_device_list_access(
@@ -335,7 +331,7 @@ void core_update_device_list_access(
struct se_dev_entry *deve;
spin_lock_irq(&nacl->device_list_lock);
- deve = &nacl->device_list[mapped_lun];
+ deve = nacl->device_list[mapped_lun];
if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
@@ -360,7 +356,7 @@ int core_update_device_list_for_node(
int enable)
{
struct se_port *port = lun->lun_sep;
- struct se_dev_entry *deve = &nacl->device_list[mapped_lun];
+ struct se_dev_entry *deve = nacl->device_list[mapped_lun];
int trans = 0;
/*
* If the MappedLUN entry is being disabled, the entry in
@@ -474,7 +470,7 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
spin_lock_irq(&nacl->device_list_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
- deve = &nacl->device_list[i];
+ deve = nacl->device_list[i];
if (lun != deve->se_lun)
continue;
spin_unlock_irq(&nacl->device_list_lock);
@@ -651,12 +647,13 @@ int target_report_luns(struct se_task *se_task)
{
struct se_cmd *se_cmd = se_task->task_se_cmd;
struct se_dev_entry *deve;
- struct se_lun *se_lun;
struct se_session *se_sess = se_cmd->se_sess;
unsigned char *buf;
- u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
+ u32 lun_count = 0, offset = 8, i;
- buf = transport_kmap_first_data_page(se_cmd);
+ buf = transport_kmap_data_sg(se_cmd);
+ if (!buf)
+ return -ENOMEM;
/*
* If no struct se_session pointer is present, this struct se_cmd is
@@ -671,22 +668,20 @@ int target_report_luns(struct se_task *se_task)
spin_lock_irq(&se_sess->se_node_acl->device_list_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
- deve = &se_sess->se_node_acl->device_list[i];
+ deve = se_sess->se_node_acl->device_list[i];
if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
continue;
- se_lun = deve->se_lun;
/*
* We determine the correct LUN LIST LENGTH even once we
* have reached the initial allocation length.
* See SPC2-R20 7.19.
*/
lun_count++;
- if ((cdb_offset + 8) >= se_cmd->data_length)
+ if ((offset + 8) > se_cmd->data_length)
continue;
int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
offset += 8;
- cdb_offset += 8;
}
spin_unlock_irq(&se_sess->se_node_acl->device_list_lock);
@@ -694,12 +689,12 @@ int target_report_luns(struct se_task *se_task)
* See SPC3 r07, page 159.
*/
done:
- transport_kunmap_first_data_page(se_cmd);
lun_count *= 8;
buf[0] = ((lun_count >> 24) & 0xff);
buf[1] = ((lun_count >> 16) & 0xff);
buf[2] = ((lun_count >> 8) & 0xff);
buf[3] = (lun_count & 0xff);
+ transport_kunmap_data_sg(se_cmd);
se_task->task_scsi_status = GOOD;
transport_complete_task(se_task, 1);
@@ -893,10 +888,15 @@ void se_dev_set_default_attribs(
limits->logical_block_size);
dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
/*
- * Set optimal_sectors from max_sectors, which can be lowered via
- * configfs.
+ * Set fabric_max_sectors, which is reported in block limits
+ * VPD page (B0h).
+ */
+ dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
+ /*
+ * Set optimal_sectors from fabric_max_sectors, which can be
+ * lowered via configfs.
*/
- dev->se_sub_dev->se_dev_attrib.optimal_sectors = limits->max_sectors;
+ dev->se_sub_dev->se_dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
/*
* queue_depth is based on subsystem plugin dependent requirements.
*/
@@ -1228,6 +1228,54 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
return 0;
}
+int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
+{
+ if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+ pr_err("dev[%p]: Unable to change SE Device"
+ " fabric_max_sectors while dev_export_obj: %d count exists\n",
+ dev, atomic_read(&dev->dev_export_obj.obj_access_count));
+ return -EINVAL;
+ }
+ if (!fabric_max_sectors) {
+ pr_err("dev[%p]: Illegal ZERO value for"
+ " fabric_max_sectors\n", dev);
+ return -EINVAL;
+ }
+ if (fabric_max_sectors < DA_STATUS_MAX_SECTORS_MIN) {
+ pr_err("dev[%p]: Passed fabric_max_sectors: %u less than"
+ " DA_STATUS_MAX_SECTORS_MIN: %u\n", dev, fabric_max_sectors,
+ DA_STATUS_MAX_SECTORS_MIN);
+ return -EINVAL;
+ }
+ if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+ if (fabric_max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
+ pr_err("dev[%p]: Passed fabric_max_sectors: %u"
+ " greater than TCM/SE_Device max_sectors:"
+ " %u\n", dev, fabric_max_sectors,
+ dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+ return -EINVAL;
+ }
+ } else {
+ if (fabric_max_sectors > DA_STATUS_MAX_SECTORS_MAX) {
+ pr_err("dev[%p]: Passed fabric_max_sectors: %u"
+ " greater than DA_STATUS_MAX_SECTORS_MAX:"
+ " %u\n", dev, fabric_max_sectors,
+ DA_STATUS_MAX_SECTORS_MAX);
+ return -EINVAL;
+ }
+ }
+ /*
+ * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
+ */
+ fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors,
+ dev->se_sub_dev->se_dev_attrib.block_size);
+
+ dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors;
+ pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
+ dev, fabric_max_sectors);
+ return 0;
+}
+
int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
{
if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
@@ -1241,10 +1289,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
" changed for TCM/pSCSI\n", dev);
return -EINVAL;
}
- if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.max_sectors) {
+ if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) {
pr_err("dev[%p]: Passed optimal_sectors %u cannot be"
- " greater than max_sectors: %u\n", dev,
- optimal_sectors, dev->se_sub_dev->se_dev_attrib.max_sectors);
+ " greater than fabric_max_sectors: %u\n", dev,
+ optimal_sectors, dev->se_sub_dev->se_dev_attrib.fabric_max_sectors);
return -EINVAL;
}
@@ -1294,24 +1342,26 @@ struct se_lun *core_dev_add_lun(
{
struct se_lun *lun_p;
u32 lun_access = 0;
+ int rc;
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
atomic_read(&dev->dev_access_obj.obj_access_count));
- return NULL;
+ return ERR_PTR(-EACCES);
}
lun_p = core_tpg_pre_addlun(tpg, lun);
- if ((IS_ERR(lun_p)) || !lun_p)
- return NULL;
+ if (IS_ERR(lun_p))
+ return lun_p;
if (dev->dev_flags & DF_READ_ONLY)
lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
else
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
- if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
- return NULL;
+ rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
+ if (rc < 0)
+ return ERR_PTR(rc);
pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -1348,11 +1398,10 @@ int core_dev_del_lun(
u32 unpacked_lun)
{
struct se_lun *lun;
- int ret = 0;
- lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
- if (!lun)
- return ret;
+ lun = core_tpg_pre_dellun(tpg, unpacked_lun);
+ if (IS_ERR(lun))
+ return PTR_ERR(lun);
core_tpg_post_dellun(tpg, lun);
@@ -1378,7 +1427,7 @@ struct se_lun *core_get_lun_from_tpg(struct se_portal_group *tpg, u32 unpacked_l
spin_unlock(&tpg->tpg_lun_lock);
return NULL;
}
- lun = &tpg->tpg_lun_list[unpacked_lun];
+ lun = tpg->tpg_lun_list[unpacked_lun];
if (lun->lun_status != TRANSPORT_LUN_STATUS_FREE) {
pr_err("%s Logical Unit Number: %u is not free on"
@@ -1411,7 +1460,7 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked
spin_unlock(&tpg->tpg_lun_lock);
return NULL;
}
- lun = &tpg->tpg_lun_list[unpacked_lun];
+ lun = tpg->tpg_lun_list[unpacked_lun];
if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
pr_err("%s Logical Unit Number: %u is not active on"