mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 02:31:27 +00:00
scst: Move RTPG and STPG handling into the SCST core
This patch does not change the behavior when using one of the vdisk handlers. When using dev_disk to forward SCSI commands from one SCST node to another, this patch causes RTPG and STPG commands to be processed on the source SCST node (as it should) instead of on the destination SCST node. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8778 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -5106,80 +5106,6 @@ static enum compl_status_e vdisk_exec_get_lba_status(struct vdisk_cmd_params *p)
|
||||
return CMD_SUCCEEDED;
|
||||
}
|
||||
|
||||
/* SPC-4 REPORT TARGET PORT GROUPS command */
|
||||
static enum compl_status_e vdisk_exec_report_tpgs(struct vdisk_cmd_params *p)
|
||||
{
|
||||
struct scst_cmd *cmd = p->cmd;
|
||||
struct scst_device *dev;
|
||||
uint8_t *address;
|
||||
void *buf;
|
||||
int32_t buf_len;
|
||||
uint32_t data_length, length;
|
||||
uint8_t data_format;
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
buf_len = scst_get_buf_full_sense(cmd, &address);
|
||||
if (buf_len <= 0)
|
||||
goto out;
|
||||
|
||||
dev = cmd->dev;
|
||||
data_format = cmd->cdb[1] >> 5;
|
||||
|
||||
res = scst_tg_get_group_info(&buf, &data_length, dev, data_format);
|
||||
if (res == -ENOMEM) {
|
||||
scst_set_busy(cmd);
|
||||
goto out_put;
|
||||
} else if (res < 0) {
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
length = min_t(uint32_t, data_length, buf_len);
|
||||
memcpy(address, buf, length);
|
||||
kfree(buf);
|
||||
if (length < cmd->resp_data_len)
|
||||
scst_set_resp_data_len(cmd, length);
|
||||
|
||||
out_put:
|
||||
scst_put_buf_full(cmd, address);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return CMD_SUCCEEDED;
|
||||
}
|
||||
|
||||
/* SPC-4 SET TARGET PORT GROUPS command */
|
||||
static enum compl_status_e vdisk_exec_set_tpgs(struct vdisk_cmd_params *p)
|
||||
{
|
||||
struct scst_cmd *cmd = p->cmd;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
int res = CMD_SUCCEEDED, rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (!dev->expl_alua) {
|
||||
PRINT_ERROR("SET TARGET PORT GROUPS: not explicit ALUA mode "
|
||||
"(dev %s)", dev->virt_name);
|
||||
/* Invalid opcode, i.e. SA field */
|
||||
scst_set_invalid_field_in_cdb(cmd, 1,
|
||||
0 | SCST_INVAL_FIELD_BIT_OFFS_VALID);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = scst_tg_set_group_info(cmd);
|
||||
if (rc == 0)
|
||||
res = RUNNING_ASYNC;
|
||||
else
|
||||
scst_stpg_del_unblock_next(cmd);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum compl_status_e vdisk_exec_sai_16(struct vdisk_cmd_params *p)
|
||||
{
|
||||
switch (p->cmd->cdb[1] & 0x1f) {
|
||||
@@ -5196,25 +5122,15 @@ static enum compl_status_e vdisk_exec_sai_16(struct vdisk_cmd_params *p)
|
||||
|
||||
static enum compl_status_e vdisk_exec_maintenance_in(struct vdisk_cmd_params *p)
|
||||
{
|
||||
switch (p->cmd->cdb[1] & 0x1f) {
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
vdisk_exec_report_tpgs(p);
|
||||
return CMD_SUCCEEDED;
|
||||
}
|
||||
scst_set_invalid_field_in_cdb(p->cmd, 1,
|
||||
0 | SCST_INVAL_FIELD_BIT_OFFS_VALID);
|
||||
return CMD_SUCCEEDED;
|
||||
/* For the code that handles RTPG, see also scst_local_cmd.c. */
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
static enum compl_status_e vdisk_exec_maintenance_out(struct vdisk_cmd_params *p)
|
||||
static enum compl_status_e
|
||||
vdisk_exec_maintenance_out(struct vdisk_cmd_params *p)
|
||||
{
|
||||
switch (p->cmd->cdb[1] & 0x1f) {
|
||||
case MO_SET_TARGET_PGS:
|
||||
return vdisk_exec_set_tpgs(p);
|
||||
}
|
||||
scst_set_invalid_field_in_cdb(p->cmd, 1,
|
||||
0 | SCST_INVAL_FIELD_BIT_OFFS_VALID);
|
||||
return CMD_SUCCEEDED;
|
||||
/* For the code that handles RTPG, see also scst_local_cmd.c. */
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
static enum compl_status_e vdisk_exec_read_toc(struct vdisk_cmd_params *p)
|
||||
|
||||
@@ -11936,7 +11936,7 @@ static int get_cdb_info_min(struct scst_cmd *cmd,
|
||||
break;
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
cmd->op_name = "REPORT TARGET PORT GROUPS";
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
|
||||
cmd->op_flags |= SCST_LOCAL_CMD | SCST_REG_RESERVE_ALLOWED |
|
||||
SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
|
||||
break;
|
||||
case MI_REPORT_SUPPORTED_OPERATION_CODES:
|
||||
@@ -11967,7 +11967,7 @@ static int get_cdb_info_mo(struct scst_cmd *cmd,
|
||||
unsigned long flags;
|
||||
|
||||
cmd->op_name = "SET TARGET PORT GROUPS";
|
||||
cmd->op_flags |= SCST_STRICTLY_SERIALIZED;
|
||||
cmd->op_flags |= SCST_LOCAL_CMD | SCST_STRICTLY_SERIALIZED;
|
||||
spin_lock_irqsave(&scst_global_stpg_list_lock, flags);
|
||||
TRACE_DBG("Adding STPG cmd %p to global_stpg_list", cmd);
|
||||
cmd->cmd_on_global_stpg_list = 1;
|
||||
|
||||
@@ -253,6 +253,82 @@ out_unlock_put_not_completed:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* SPC-4 REPORT TARGET PORT GROUPS command */
|
||||
static enum scst_exec_res scst_report_tpgs(struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
uint8_t *address;
|
||||
void *buf;
|
||||
int32_t buf_len;
|
||||
uint32_t data_length, length;
|
||||
uint8_t data_format;
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
buf_len = scst_get_buf_full_sense(cmd, &address);
|
||||
if (buf_len <= 0)
|
||||
goto out;
|
||||
|
||||
dev = cmd->dev;
|
||||
data_format = cmd->cdb[1] >> 5;
|
||||
|
||||
res = scst_tg_get_group_info(&buf, &data_length, dev, data_format);
|
||||
if (res == -ENOMEM) {
|
||||
scst_set_busy(cmd);
|
||||
goto out_put;
|
||||
} else if (res < 0) {
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
length = min_t(uint32_t, data_length, buf_len);
|
||||
memcpy(address, buf, length);
|
||||
kfree(buf);
|
||||
if (length < cmd->resp_data_len)
|
||||
scst_set_resp_data_len(cmd, length);
|
||||
|
||||
out_put:
|
||||
scst_put_buf_full(cmd, address);
|
||||
|
||||
out:
|
||||
cmd->completed = 1;
|
||||
|
||||
/* Report the result */
|
||||
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
|
||||
|
||||
return SCST_EXEC_COMPLETED;
|
||||
}
|
||||
|
||||
/* SPC-4 SET TARGET PORT GROUPS command */
|
||||
static enum scst_exec_res scst_exec_set_tpgs(struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_device *dev = cmd->dev;
|
||||
int rc;
|
||||
|
||||
if (!dev->expl_alua) {
|
||||
PRINT_ERROR("SET TARGET PORT GROUPS: not explicit ALUA mode "
|
||||
"(dev %s)", dev->virt_name);
|
||||
/* Invalid opcode, i.e. SA field */
|
||||
scst_set_invalid_field_in_cdb(cmd, 1,
|
||||
0 | SCST_INVAL_FIELD_BIT_OFFS_VALID);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = scst_tg_set_group_info(cmd);
|
||||
if (rc == 0) {
|
||||
/* Running async */
|
||||
return SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
}
|
||||
scst_stpg_del_unblock_next(cmd);
|
||||
|
||||
out:
|
||||
cmd->completed = 1;
|
||||
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
|
||||
return SCST_EXEC_COMPLETED;
|
||||
}
|
||||
|
||||
static enum scst_exec_res scst_report_supported_tm_fns(struct scst_cmd *cmd)
|
||||
{
|
||||
const enum scst_exec_res res = SCST_EXEC_COMPLETED;
|
||||
@@ -505,6 +581,9 @@ enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
switch (cmd->cdb[1] & 0x1f) {
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
res = scst_report_tpgs(cmd);
|
||||
break;
|
||||
case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
|
||||
res = scst_report_supported_tm_fns(cmd);
|
||||
break;
|
||||
@@ -520,6 +599,22 @@ enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd)
|
||||
return res;
|
||||
}
|
||||
|
||||
enum scst_exec_res scst_maintenance_out(struct scst_cmd *cmd)
|
||||
{
|
||||
enum scst_exec_res res;
|
||||
|
||||
switch (cmd->cdb[1] & 0x1f) {
|
||||
case MO_SET_TARGET_PGS:
|
||||
res = scst_exec_set_tpgs(cmd);
|
||||
break;
|
||||
default:
|
||||
res = SCST_EXEC_NOT_COMPLETED;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
enum scst_exec_res scst_reserve_local(struct scst_cmd *cmd)
|
||||
{
|
||||
enum scst_exec_res res = SCST_EXEC_NOT_COMPLETED;
|
||||
|
||||
@@ -8,6 +8,7 @@ enum scst_exec_res scst_cm_ext_copy_exec(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_cm_rcv_copy_res_exec(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_cmp_wr_local(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_maintenance_in(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_maintenance_out(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_persistent_reserve_in_local(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_persistent_reserve_out_local(struct scst_cmd *cmd);
|
||||
enum scst_exec_res scst_release_local(struct scst_cmd *cmd);
|
||||
|
||||
@@ -2708,6 +2708,7 @@ static scst_local_exec_fn scst_local_fns[256] = {
|
||||
[EXTENDED_COPY] = scst_cm_ext_copy_exec,
|
||||
[RECEIVE_COPY_RESULTS] = scst_cm_rcv_copy_res_exec,
|
||||
[MAINTENANCE_IN] = scst_maintenance_in,
|
||||
[MAINTENANCE_OUT] = scst_maintenance_out,
|
||||
};
|
||||
|
||||
static enum scst_exec_res scst_do_local_exec(struct scst_cmd *cmd)
|
||||
|
||||
Reference in New Issue
Block a user