^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) TCM Userspace Design
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) .. Contents:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) 1) Design
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) a) Background
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) b) Benefits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) c) Design constraints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) d) Implementation overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) i. Mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) ii. Command ring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) iii. Data Area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) e) Device discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) f) Device events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) g) Other contingencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) 2) Writing a user pass-through handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) a) Discovering and configuring TCMU uio devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) b) Waiting for events on the device(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) c) Managing the command ring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) 3) A final note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) Design
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ======
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) TCM is another name for LIO, an in-kernel iSCSI target (server).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) Existing TCM targets run in the kernel. TCMU (TCM in Userspace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) allows userspace programs to be written which act as iSCSI targets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) This document describes the design.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) The existing kernel provides modules for different SCSI transport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) protocols. TCM also modularizes the data storage. There are existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) modules for file, block device, RAM or using another SCSI device as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) storage. These are called "backstores" or "storage engines". These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) built-in modules are implemented entirely as kernel code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) Background
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) In addition to modularizing the transport protocol used for carrying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) SCSI commands ("fabrics"), the Linux kernel target, LIO, also modularizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) the actual data storage as well. These are referred to as "backstores"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) or "storage engines". The target comes with backstores that allow a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) file, a block device, RAM, or another SCSI device to be used for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) local storage needed for the exported SCSI LUN. Like the rest of LIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) these are implemented entirely as kernel code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) These backstores cover the most common use cases, but not all. One new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) use case that other non-kernel target solutions, such as tgt, are able
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) to support is using Gluster's GLFS or Ceph's RBD as a backstore. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) target then serves as a translator, allowing initiators to store data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) in these non-traditional networked storage systems, while still only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) using standard protocols themselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) If the target is a userspace process, supporting these is easy. tgt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) for example, needs only a small adapter module for each, because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) modules just use the available userspace libraries for RBD and GLFS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) Adding support for these backstores in LIO is considerably more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) difficult, because LIO is entirely kernel code. Instead of undertaking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) the significant work to port the GLFS or RBD APIs and protocols to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) kernel, another approach is to create a userspace pass-through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) backstore for LIO, "TCMU".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) Benefits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) In addition to allowing relatively easy support for RBD and GLFS, TCMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) will also allow easier development of new backstores. TCMU combines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) with the LIO loopback fabric to become something similar to FUSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) (Filesystem in Userspace), but at the SCSI layer instead of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) filesystem layer. A SUSE, if you will.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) The disadvantage is there are more distinct components to configure, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) potentially to malfunction. This is unavoidable, but hopefully not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) fatal if we're careful to keep things as simple as possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) Design constraints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) - Good performance: high throughput, low latency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) - Cleanly handle if userspace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 1) never attaches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 2) hangs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 3) dies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 4) misbehaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) - Allow future flexibility in user & kernel implementations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) - Be reasonably memory-efficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) - Simple to configure & run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) - Simple to write a userspace backend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) Implementation overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) -----------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) The core of the TCMU interface is a memory region that is shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) between kernel and userspace. Within this region is: a control area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) (mailbox); a lockless producer/consumer circular buffer for commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) to be passed up, and status returned; and an in/out data buffer area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) TCMU uses the pre-existing UIO subsystem. UIO allows device driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) development in userspace, and this is conceptually very close to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) TCMU use case, except instead of a physical device, TCMU implements a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) memory-mapped layout designed for SCSI commands. Using UIO also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) benefits TCMU by handling device introspection (e.g. a way for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) userspace to determine how large the shared region is) and signaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mechanisms in both directions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) There are no embedded pointers in the memory region. Everything is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) expressed as an offset from the region's starting address. This allows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) the ring to still work if the user process dies and is restarted with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) the region mapped at a different virtual address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) See target_core_user.h for the struct definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) The Mailbox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) The mailbox is always at the start of the shared memory region, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) contains a version, details about the starting offset and size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) command ring, and head and tail pointers to be used by the kernel and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) userspace (respectively) to put commands on the ring, and indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) when the commands are completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) version - 1 (userspace should abort if otherwise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) flags:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) - TCMU_MAILBOX_FLAG_CAP_OOOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) indicates out-of-order completion is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) See "The Command Ring" for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cmdr_off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) The offset of the start of the command ring from the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) of the memory region, to account for the mailbox size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) cmdr_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) The size of the command ring. This does *not* need to be a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) power of two.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cmd_head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) Modified by the kernel to indicate when a command has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) placed on the ring.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) cmd_tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) Modified by userspace to indicate when it has completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) processing of a command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) The Command Ring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) Commands are placed on the ring by the kernel incrementing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mailbox.cmd_head by the size of the command, modulo cmdr_size, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) then signaling userspace via uio_event_notify(). Once the command is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) completed, userspace updates mailbox.cmd_tail in the same way and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) signals the kernel via a 4-byte write(). When cmd_head equals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) cmd_tail, the ring is empty -- no commands are currently waiting to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) processed by userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) TCMU commands are 8-byte aligned. They start with a common header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) containing "len_op", a 32-bit value that stores the length, as well as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) the opcode in the lowest unused bits. It also contains cmd_id and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) flags fields for setting by the kernel (kflags) and userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) (uflags).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) Currently only two opcodes are defined, TCMU_OP_CMD and TCMU_OP_PAD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) When the opcode is CMD, the entry in the command ring is a struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) tcmu_cmd_entry. Userspace finds the SCSI CDB (Command Data Block) via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) tcmu_cmd_entry.req.cdb_off. This is an offset from the start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) overall shared memory region, not the entry. The data in/out buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) are accessible via tht req.iov[] array. iov_cnt contains the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) entries in iov[] needed to describe either the Data-In or Data-Out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) buffers. For bidirectional commands, iov_cnt specifies how many iovec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) entries cover the Data-Out area, and iov_bidi_cnt specifies how many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) iovec entries immediately after that in iov[] cover the Data-In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) area. Just like other fields, iov.iov_base is an offset from the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) of the region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) When completing a command, userspace sets rsp.scsi_status, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) rsp.sense_buffer if necessary. Userspace then increments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kernel via the UIO method, a 4-byte write to the file descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) If TCMU_MAILBOX_FLAG_CAP_OOOC is set for mailbox->flags, kernel is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) capable of handling out-of-order completions. In this case, userspace can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) handle command in different order other than original. Since kernel would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) still process the commands in the same order it appeared in the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ring, userspace need to update the cmd->id when completing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) command(a.k.a steal the original command's entry).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) When the opcode is PAD, userspace only updates cmd_tail as above --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) it's a no-op. (The kernel inserts PAD entries to ensure each CMD entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) is contiguous within the command ring.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) More opcodes may be added in the future. If userspace encounters an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) opcode it does not handle, it must set UNKNOWN_OP bit (bit 0) in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) hdr.uflags, update cmd_tail, and proceed with processing additional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) commands, if any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) The Data Area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) -------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) This is shared-memory space after the command ring. The organization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) of this area is not defined in the TCMU interface, and userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) should access only the parts referenced by pending iovs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) Device Discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) Other devices may be using UIO besides TCMU. Unrelated user processes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) may also be handling different sets of TCMU devices. TCMU userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) processes must find their devices by scanning sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) class/uio/uio*/name. For TCMU devices, these names will be of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) format::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) tcm-user/<hba_num>/<device_name>/<subtype>/<path>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) where "tcm-user" is common for all TCMU-backed UIO devices. <hba_num>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) and <device_name> allow userspace to find the device's path in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) kernel target's configfs tree. Assuming the usual mount point, it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) found at::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /sys/kernel/config/target/core/user_<hba_num>/<device_name>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) This location contains attributes such as "hw_block_size", that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) userspace needs to know for correct operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) <subtype> will be a userspace-process-unique string to identify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) TCMU device as expecting to be backed by a certain handler, and <path>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) will be an additional handler-specific string for the user process to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) configure the device, if needed. The name cannot contain ':', due to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) LIO limitations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) For all devices so discovered, the user handler opens /dev/uioX and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) calls mmap()::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) where size must be equal to the value read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /sys/class/uio/uioX/maps/map0/size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) Device Events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) -------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) If a new device is added or removed, a notification will be broadcast
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) over netlink, using a generic netlink family name of "TCM-USER" and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) multicast group named "config". This will include the UIO name as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) described in the previous section, as well as the UIO minor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) number. This should allow userspace to identify both the UIO device and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) the LIO device, so that after determining the device is supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) (based on subtype) it can take the appropriate action.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) Other contingencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) -------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) Userspace handler process never attaches:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) - TCMU will post commands, and then abort them after a timeout period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) (30 seconds.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) Userspace handler process is killed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) - It is still possible to restart and re-connect to TCMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) devices. Command ring is preserved. However, after the timeout period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) the kernel will abort pending tasks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) Userspace handler process hangs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) - The kernel will abort pending tasks after a timeout period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) Userspace handler process is malicious:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) - The process can trivially break the handling of devices it controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) but should not be able to access kernel memory outside its shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) memory areas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) Writing a user pass-through handler (with example code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) =======================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) A user process handing a TCMU device must support the following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) a) Discovering and configuring TCMU uio devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) b) Waiting for events on the device(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) c) Managing the command ring: Parsing operations and commands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) performing work as needed, setting response fields (scsi_status and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) possibly sense_buffer), updating cmd_tail, and notifying the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) that work has been finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) First, consider instead writing a plugin for tcmu-runner. tcmu-runner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) implements all of this, and provides a higher-level API for plugin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) authors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) TCMU is designed so that multiple unrelated processes can manage TCMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) devices separately. All handlers should make sure to only open their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) devices, based opon a known subtype string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) a) Discovering and configuring TCMU UIO devices::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* error checking omitted for brevity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int fd, dev_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) char buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned long long map_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) void *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) fd = open("/sys/class/uio/uio0/name", O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ret = read(fd, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* we only want uio devices whose name is a format we expect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (strncmp(buf, "tcm-user", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) exit(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Further checking for subtype also needed here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) fd = open(/sys/class/uio/%s/maps/map0/size, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = read(fd, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) str_buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) map_len = strtoull(buf, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) dev_fd = open("/dev/uio0", O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) map = mmap(NULL, map_len, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) b) Waiting for events on the device(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) char buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int ret = read(dev_fd, buf, 4); /* will block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) handle_device_events(dev_fd, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) c) Managing the command ring::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #include <linux/target_core_user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int handle_device_events(int fd, void *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct tcmu_mailbox *mb = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int did_some_work = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* Process events from cmd ring until we catch up with cmd_head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (tcmu_hdr_get_op(ent->hdr.len_op) == TCMU_OP_CMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) uint8_t *cdb = (void *)mb + ent->req.cdb_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) bool success = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Handle command here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) printf("SCSI opcode: 0x%x\n", cdb[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Set response fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ent->rsp.scsi_status = SCSI_NO_SENSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* Also fill in rsp->sense_buffer here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) else if (tcmu_hdr_get_op(ent->hdr.len_op) != TCMU_OP_PAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Tell the kernel we didn't handle unknown opcodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ent->hdr.uflags |= TCMU_UFLAG_UNKNOWN_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Do nothing for PAD entries except update cmd_tail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* update cmd_tail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) did_some_work = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Notify the kernel that work has been finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (did_some_work) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) uint32_t buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) write(fd, &buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) A final note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ============
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) Please be careful to return codes as defined by the SCSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) specifications. These are different than some values defined in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) scsi/scsi.h include file. For example, CHECK CONDITION's status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) is 2, not 1.