X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=drivers%2Ftarget%2Ftarget_core_device.c;h=aa6267746383b5070148ac894d27d1706e14e144;hb=7bf97e1d5a94b6a71815771bb9452fc2c022c966;hp=edbcabbf85f7339d1eddef7d618b26181540cd5a;hpb=0d9cabdccedb79ee5f27b77ff51f29a9e7d23275;p=~andy%2Flinux diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index edbcabbf85f..aa626774638 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; @@ -323,7 +318,7 @@ void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd) unsigned long flags; spin_lock_irqsave(&se_nacl->device_list_lock, flags); - deve = &se_nacl->device_list[se_cmd->orig_fe_lun]; + deve = se_nacl->device_list[se_cmd->orig_fe_lun]; deve->deve_cmds--; spin_unlock_irqrestore(&se_nacl->device_list_lock, flags); } @@ -336,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; @@ -361,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 @@ -475,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); @@ -652,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 = (unsigned char *) transport_kmap_data_sg(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 @@ -672,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); @@ -695,12 +689,12 @@ int target_report_luns(struct se_task *se_task) * See SPC3 r07, page 159. */ done: - transport_kunmap_data_sg(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); @@ -894,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.optimal_sectors = limits->max_sectors; + 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 = DA_FABRIC_MAX_SECTORS; /* * queue_depth is based on subsystem plugin dependent requirements. */ @@ -1229,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)) { @@ -1242,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; } @@ -1380,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" @@ -1413,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"