diff --git a/doc/scst_user_spec.txt b/doc/scst_user_spec.txt index 7f1a4aca2..1f4ed23e1 100644 --- a/doc/scst_user_spec.txt +++ b/doc/scst_user_spec.txt @@ -850,6 +850,7 @@ struct scst_user_scsi_cmd_reply_parse uint32_t op_flags; int32_t data_len; int32_t bufflen; + int32_t out_bufflen; }, where: @@ -857,7 +858,7 @@ where: - queue_type - SCSI task attribute (queue type). NOTE! In current implementation setting changing this field from the provided value affects commands execution only when then produced by iSCSI-SCST - target. With al other target drivers, this field is ignored. This is + target. With all other target drivers, this field is ignored. This is because for them commands queueing is set before parse() called. - data_direction - command's data flow direction, one of SCST_DATA_* @@ -866,11 +867,17 @@ where: - cdb_len - length of CDB - op_flags - commands flags, one or more scst_cdb_flags bits, see above. + At least SCST_INFO_VALID must be set for correct processing. + SCST_IMPLICIT_HQ not implemented (yet) for single stage init target + drivers (all, except iSCSI), because custom parse can reorder + commands due to multithreaded processing. - data_len - command's data length - bufflen - command's buffer length + - out_bufflen - command's out buffer length (for bidirectional commands) + struct scst_user_scsi_cmd_reply_alloc_mem { diff --git a/scst/include/scst_user.h b/scst/include/scst_user.h index 8b19075bf..53b7584ea 100644 --- a/scst/include/scst_user.h +++ b/scst/include/scst_user.h @@ -227,6 +227,7 @@ struct scst_user_scsi_cmd_reply_parse { uint32_t op_flags; int32_t data_len; int32_t bufflen; + int32_t out_bufflen; }; struct { uint8_t sense_len; diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 2358580c5..1e7d34de7 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1272,12 +1272,16 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, (preply->bufflen == 0))) goto out_inval; - if (unlikely((preply->bufflen < 0) || (preply->data_len < 0))) + if (unlikely((preply->bufflen < 0) || (preply->out_bufflen < 0) || + (preply->data_len < 0))) goto out_inval; if (unlikely(preply->cdb_len > cmd->cdb_len)) goto out_inval; + if (!(preply->op_flags & SCST_INFO_VALID)) + goto out_inval; + TRACE_DBG("ucmd %p, queue_type %x, data_direction, %x, bufflen %d, " "data_len %d, pbuf %llx, cdb_len %d, op_flags %x", ucmd, preply->queue_type, preply->data_direction, preply->bufflen, @@ -1287,11 +1291,11 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, cmd->queue_type = preply->queue_type; cmd->data_direction = preply->data_direction; cmd->bufflen = preply->bufflen; + cmd->out_bufflen = preply->out_bufflen; cmd->data_len = preply->data_len; if (preply->cdb_len > 0) cmd->cdb_len = preply->cdb_len; - if (preply->op_flags & SCST_INFO_VALID) - cmd->op_flags = preply->op_flags; + cmd->op_flags = preply->op_flags; out_process: scst_post_parse(cmd); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index a56e98618..319ea0bda 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3845,8 +3845,15 @@ static int __scst_init_cmd(struct scst_cmd *cmd) if (unlikely(failure)) goto out_busy; - if (unlikely(scst_pre_parse(cmd) != 0)) - goto out; + /* + * SCST_IMPLICIT_HQ for unknown commands not implemented for + * case when set_sn_on_restart_cmd not set, because custom parse + * can reorder commands due to multithreaded processing. To + * implement it we need to implement all unknown commands as + * ORDERED in the beginning and post parse reprocess of + * queue_type to change it if needed. ToDo. + */ + scst_pre_parse(cmd); if (!cmd->set_sn_on_restart_cmd) scst_cmd_set_sn(cmd); diff --git a/usr/fileio/common.c b/usr/fileio/common.c index e8199b5bd..17dfff0bf 100644 --- a/usr/fileio/common.c +++ b/usr/fileio/common.c @@ -192,8 +192,18 @@ static int do_parse(struct vdisk_cmd *vcmd) reply->data_direction = cmd->expected_data_direction; reply->data_len = cmd->expected_transfer_len; reply->bufflen = cmd->expected_transfer_len; + reply->out_bufflen = cmd->expected_out_transfer_len; reply->cdb_len = cmd->cdb_len; - reply->op_flags = reply->op_flags; + + if (cmd->op_flags & SCST_INFO_VALID) + reply->op_flags = cmd->op_flags; + else { + TRACE_DBG_SPECIAL("Extra parse (op %x)", cmd->cdb[0]); + + if (reply->data_direction & SCST_DATA_WRITE) + reply->op_flags |= SCST_WRITE_MEDIUM; + reply->op_flags |= SCST_INFO_VALID; + } out: TRACE_EXIT_RES(res);