Documentation/target/tcmu-design.rst

Source file repositories/reference/linux-study-clean/Documentation/target/tcmu-design.rst

File Facts

System
Linux kernel
Corpus path
Documentation/target/tcmu-design.rst
Extension
.rst
Size
14378 bytes
Lines
406
Domain
Support Tooling And Documentation
Bucket
Documentation
Inferred role
Support Tooling And Documentation: documentation
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

while (1) {
        char buf[4];

        int ret = read(dev_fd, buf, 4); /* will block */

        handle_device_events(dev_fd, map);
      }


c) Managing the command ring::

      #include <linux/target_core_user.h>

      int handle_device_events(int fd, void *map)
      {
        struct tcmu_mailbox *mb = map;
        struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
        int did_some_work = 0;

        /* Process events from cmd ring until we catch up with cmd_head */
        while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {

          if (tcmu_hdr_get_op(ent->hdr.len_op) == TCMU_OP_CMD) {
            uint8_t *cdb = (void *)mb + ent->req.cdb_off;
            bool success = true;

            /* Handle command here. */
            printf("SCSI opcode: 0x%x\n", cdb[0]);

            /* Set response fields */
            if (success)
              ent->rsp.scsi_status = SCSI_NO_SENSE;
            else {
              /* Also fill in rsp->sense_buffer here */
              ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
            }
          }
          else if (tcmu_hdr_get_op(ent->hdr.len_op) != TCMU_OP_PAD) {
            /* Tell the kernel we didn't handle unknown opcodes */
            ent->hdr.uflags |= TCMU_UFLAG_UNKNOWN_OP;
          }
          else {
            /* Do nothing for PAD entries except update cmd_tail */
          }

          /* update cmd_tail */
          mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
          ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
          did_some_work = 1;
        }

        /* Notify the kernel that work has been finished */
        if (did_some_work) {
          uint32_t buf = 0;

          write(fd, &buf, 4);
        }

        return 0;
      }


A final note
============

Please be careful to return codes as defined by the SCSI
specifications. These are different than some values defined in the
scsi/scsi.h include file. For example, CHECK CONDITION's status code
is 2, not 1.

Annotation

Implementation Notes