From: Christoph Hellwig Date: Sun, 7 Oct 2012 14:55:51 +0000 (-0400) Subject: target: move REPORT LUNS emulation to target_core_spc.c X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=d1b1f8053401aaf1dfe636afa6d361301e3ae8b7;p=linux-beck.git target: move REPORT LUNS emulation to target_core_spc.c Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b27c75a0e2e2..e45a70970548 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -646,69 +646,6 @@ void core_dev_unexport( lun->lun_se_dev = NULL; } -int target_report_luns(struct se_cmd *se_cmd) -{ - struct se_dev_entry *deve; - struct se_session *se_sess = se_cmd->se_sess; - unsigned char *buf; - u32 lun_count = 0, offset = 8, i; - - if (se_cmd->data_length < 16) { - pr_warn("REPORT LUNS allocation length %u too small\n", - se_cmd->data_length); - se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - - buf = transport_kmap_data_sg(se_cmd); - if (!buf) - return -ENOMEM; - - /* - * If no struct se_session pointer is present, this struct se_cmd is - * coming via a target_core_mod PASSTHROUGH op, and not through - * a $FABRIC_MOD. In that case, report LUN=0 only. - */ - if (!se_sess) { - int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); - lun_count = 1; - goto done; - } - - 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]; - if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) - continue; - /* - * We determine the correct LUN LIST LENGTH even once we - * have reached the initial allocation length. - * See SPC2-R20 7.19. - */ - lun_count++; - if ((offset + 8) > se_cmd->data_length) - continue; - - int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); - offset += 8; - } - spin_unlock_irq(&se_sess->se_node_acl->device_list_lock); - - /* - * See SPC3 r07, page 159. - */ -done: - 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); - - target_complete_cmd(se_cmd, GOOD); - return 0; -} - static void se_release_vpd_for_dev(struct se_device *dev) { struct t10_vpd *vpd, *vpd_tmp; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 5854ed67af59..2f37720c4db3 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -19,7 +19,6 @@ int core_dev_export(struct se_device *, struct se_portal_group *, struct se_lun *); void core_dev_unexport(struct se_device *, struct se_portal_group *, struct se_lun *); -int target_report_luns(struct se_cmd *); int se_dev_set_task_timeout(struct se_device *, u32); int se_dev_set_max_unmap_lba_count(struct se_device *, u32); int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 0af45ae32f8c..07b82700dcd8 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -908,6 +908,69 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return 0; } +static int spc_emulate_report_luns(struct se_cmd *cmd) +{ + struct se_dev_entry *deve; + struct se_session *sess = cmd->se_sess; + unsigned char *buf; + u32 lun_count = 0, offset = 8, i; + + if (cmd->data_length < 16) { + pr_warn("REPORT LUNS allocation length %u too small\n", + cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + + buf = transport_kmap_data_sg(cmd); + if (!buf) + return -ENOMEM; + + /* + * If no struct se_session pointer is present, this struct se_cmd is + * coming via a target_core_mod PASSTHROUGH op, and not through + * a $FABRIC_MOD. In that case, report LUN=0 only. + */ + if (!sess) { + int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); + lun_count = 1; + goto done; + } + + spin_lock_irq(&sess->se_node_acl->device_list_lock); + for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { + deve = sess->se_node_acl->device_list[i]; + if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) + continue; + /* + * We determine the correct LUN LIST LENGTH even once we + * have reached the initial allocation length. + * See SPC2-R20 7.19. + */ + lun_count++; + if ((offset + 8) > cmd->data_length) + continue; + + int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); + offset += 8; + } + spin_unlock_irq(&sess->se_node_acl->device_list_lock); + + /* + * See SPC3 r07, page 159. + */ +done: + 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(cmd); + + target_complete_cmd(cmd, GOOD); + return 0; +} + static int spc_emulate_testunitready(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); @@ -1013,7 +1076,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; break; case REPORT_LUNS: - cmd->execute_cmd = target_report_luns; + cmd->execute_cmd = spc_emulate_report_luns; *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; /* * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS