Hi Nicholas & Andy, I am working on adding support for BIDI operations to the TCM Userspace module and I would like to discuss the implementation details with you, before submitting the patches. First, some initial observations from my efforts to understand the current implementation of the TCM Userspace module. TCMU commands start with a common header containing "len_op", a 32-bit value that stores the length (higher-order bits) and the opcode (unused lower-oreder bits). Currently only two opcodes are defined, TCMU_OP_PAD and TCMU_OP_CMD. When userspace handles a CMD, it finds the SCSI CDB via tcmu_cmd_entry.req.cdb_off. The data-in/data-out buffers are accessible via the req.iov[] array. The length of the req.iov[] array is stored in the req.iov_cnt variable. The problem is, that BIDI commands need both data-in and data-out buffers, but the current tcmu_cmd_entry only contains a single iov_cnt field. My initial thought was to add a new variable named req.bidi_cnt to the tcmu_cmd_entry structure like this: diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h index b483d19..d861cde 100644 --- a/include/uapi/linux/target_core_user.h +++ b/include/uapi/linux/target_core_user.h @@ -104,6 +104,7 @@ struct tcmu_cmd_entry { struct { uint64_t cdb_off; uint64_t iov_cnt; + uint64_t bidi_cnt; struct iovec iov[0]; } req; struct { When a SCSI command refers to both data-out and data-in buffers, the first iov_cnt items in req.iov[] will form the data-out buffer and the remaining bidi_cnt items in req.iov[] will form the data-in buffer. Otherwise, if the command needs only one of data-out/data-in buffers, the first iov_cnt items in req.iov[] will form the data-out/data-in buffer and bidi_cnt will be set to 0. The above implementation breaks the TCM Userspace ABI, so it's probably not an acceptable solution. Instead, I propose the following change: diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h index b483d19..837ca8a 100644 --- a/include/uapi/linux/target_core_user.h +++ b/include/uapi/linux/target_core_user.h @@ -58,6 +58,7 @@ struct tcmu_mailbox { enum tcmu_opcode { TCMU_OP_PAD = 0, TCMU_OP_CMD, + TCMU_OP_BIDI, }; /* @@ -103,8 +104,17 @@ struct tcmu_cmd_entry { union { struct { uint64_t cdb_off; - uint64_t iov_cnt; - struct iovec iov[0]; + union { + struct { + uint64_t iov_cnt; + struct iovec iov[0]; + }; + struct { + uint64_t out_cnt; + uint64_t in_cnt; + struct iovec bidi_iov[0]; + }; + }; } req; struct { uint8_t scsi_status; In the above change, a new TCMU command opcode is introduced, namely TCMU_OP_BIDI. When opcode is TCMU_OP_CMD, the SCSI command needs only one of data-out/data-in buffers and everything works as before. But when the SCSI command needs to have both data-out and data-in buffers, TCMU command opcode is set to TCMU_OP_BIDI and the user is expected to access the data-out buffer in the first 'out_cnt' items in req.bidi_iov[] and the data-in buffer in the remaining 'in_cnt' items in req.bidi_iov[]. This enables support for BIDI SCSI operations without breaking backwards compatibility. What do you think? Shall I continue with the proposed changes? Thanks, Ilias
Attachment:
signature.asc
Description: Digital signature