Documentation
¶
Overview ¶
errors.go defines the public error hierarchy for the uiscsi package. All errors support errors.As/errors.Is for inspection.
options.go defines functional options for Dial and Discover.
sense.go provides public sense data parsing and status checking helpers for callers of Execute and StreamExecute.
session.go defines the Session type, accessor methods for grouped APIs, and deprecated flat methods for backward compatibility.
types.go defines the public wrapper types for the uiscsi package. All types are defined in the root package to avoid exposing internal types.
Package uiscsi provides a pure-userspace iSCSI initiator library. It handles TCP connection, login negotiation, and SCSI command transport over iSCSI PDUs entirely in userspace.
Quick Start ¶
sess, err := uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
)
if err != nil { ... }
defer sess.Close()
data, err := sess.SCSI().ReadBlocks(ctx, 0, 0, 1, 512)
API Tiers ¶
uiscsi provides three tiers of SCSI command access, each with different error handling. Choose based on your use case:
## Tier 1: Typed SCSI Methods (recommended for common operations)
Access via Session.SCSI. Returns parsed Go types. CHECK CONDITION is automatically converted to *SCSIError.
data, err := sess.SCSI().ReadBlocks(ctx, lun, lba, blocks, blockSize) inq, err := sess.SCSI().Inquiry(ctx, lun) err := sess.SCSI().ModeSelect6(ctx, lun, modeData)
## Tier 2: Buffered Raw CDB (for device-specific commands)
Access via Session.Raw. Returns raw status + sense bytes. The caller interprets SCSI status. Use CheckStatus or ParseSenseData for convenience.
result, err := sess.Raw().Execute(ctx, lun, cdb, uiscsi.WithDataIn(256))
if err := uiscsi.CheckStatus(result.Status, result.SenseData); err != nil { ... }
## Tier 3: Streaming Raw CDB (for high-throughput sequential I/O)
Access via Session.Raw. Response data delivered as io.Reader with bounded memory (~64KB). Critical for tape drives and large block transfers.
sr, err := sess.Raw().StreamExecute(ctx, lun, cdb, uiscsi.WithDataIn(blockSize)) _, err = io.Copy(dst, sr.Data) status, sense, err := sr.Wait()
Performance Tuning ¶
The default MaxRecvDataSegmentLength is 8192 bytes (8KB per PDU). For high-throughput workloads (tape, large block I/O), increase it with WithMaxRecvDataSegmentLength:
sess, err := uiscsi.Dial(ctx, addr,
uiscsi.WithTarget(iqn),
uiscsi.WithMaxRecvDataSegmentLength(262144), // 256KB per PDU
)
This reduces per-PDU overhead and improves streaming throughput. With StreamExecute, the bounded-memory window scales with MRDSL: 8 chunks × MRDSL bytes (e.g., 8 × 256KB = 2MB in-flight with 256KB MRDSL).
Other API Groups ¶
Task management: Session.TMF — AbortTask, LUNReset, TargetWarmReset, etc.
Protocol operations: Session.Protocol — Logout, SendExpStatSNConfirmation.
Index ¶
- func CheckStatus(status uint8, senseData []byte) error
- func DecodeLUN(raw uint64) uint64
- func DeviceTypeName(code uint8) string
- type AsyncEvent
- type AuthError
- type Capacity
- type ExecuteOption
- type InquiryData
- type MetricEvent
- type MetricEventType
- type Option
- func WithAsyncHandler(h func(context.Context, AsyncEvent)) Option
- func WithCHAP(user, secret string) Option
- func WithDataDigest(prefs ...string) Option
- func WithDigestByteOrder(bo binary.ByteOrder) Option
- func WithFirstBurstLength(size uint32) Option
- func WithHeaderDigest(prefs ...string) Option
- func WithInitiatorName(iqn string) Option
- func WithKeepaliveInterval(d time.Duration) Option
- func WithKeepaliveTimeout(d time.Duration) Option
- func WithLogger(l *slog.Logger) Option
- func WithMaxBurstLength(size uint32) Option
- func WithMaxReconnectAttempts(n int) Option
- func WithMaxRecvDataSegmentLength(size uint32) Option
- func WithMetricsHook(h func(MetricEvent)) Option
- func WithMutualCHAP(user, secret, targetSecret string) Option
- func WithOperationalOverrides(overrides map[string]string) Option
- func WithPDUHook(h func(context.Context, PDUDirection, []byte)) Option
- func WithReconnectBackoff(base time.Duration) Option
- func WithRouterBufDepth(depth int) Option
- func WithSNACKTimeout(d time.Duration) Option
- func WithStreamBufDepth(depth int) Option
- func WithTarget(iqn string) Option
- type PDUDirection
- type Portal
- type ProtocolOps
- type RawOps
- type RawResult
- type SCSIError
- type SCSIOps
- func (o *SCSIOps) CompareAndWrite(ctx context.Context, lun uint64, lba uint64, blocks uint8, blockSize uint32, ...) error
- func (o *SCSIOps) Inquiry(ctx context.Context, lun uint64) (*InquiryData, error)
- func (o *SCSIOps) ModeSelect6(ctx context.Context, lun uint64, data []byte) error
- func (o *SCSIOps) ModeSelect10(ctx context.Context, lun uint64, data []byte) error
- func (o *SCSIOps) ModeSense6(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)
- func (o *SCSIOps) ModeSense10(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)
- func (o *SCSIOps) PersistReserveIn(ctx context.Context, lun uint64, serviceAction uint8) ([]byte, error)
- func (o *SCSIOps) PersistReserveOut(ctx context.Context, lun uint64, serviceAction, scopeType uint8, ...) error
- func (o *SCSIOps) ReadBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32) ([]byte, error)
- func (o *SCSIOps) ReadCapacity(ctx context.Context, lun uint64) (*Capacity, error)
- func (o *SCSIOps) ReportLuns(ctx context.Context) ([]uint64, error)
- func (o *SCSIOps) RequestSense(ctx context.Context, lun uint64) (*SenseInfo, error)
- func (o *SCSIOps) StartStopUnit(ctx context.Context, lun uint64, powerCondition uint8, start, loadEject bool) error
- func (o *SCSIOps) SynchronizeCache(ctx context.Context, lun uint64) error
- func (o *SCSIOps) TestUnitReady(ctx context.Context, lun uint64) error
- func (o *SCSIOps) Unmap(ctx context.Context, lun uint64, descriptors []UnmapBlockDescriptor) error
- func (o *SCSIOps) Verify(ctx context.Context, lun uint64, lba uint64, blocks uint32) error
- func (o *SCSIOps) WriteBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32, ...) error
- func (o *SCSIOps) WriteSame(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32, ...) error
- type SenseInfo
- type Session
- func (s *Session) AbortTask(ctx context.Context, taskTag uint32) (*TMFResult, error)deprecated
- func (s *Session) AbortTaskSet(ctx context.Context, lun uint64) (*TMFResult, error)deprecated
- func (s *Session) ClearTaskSet(ctx context.Context, lun uint64) (*TMFResult, error)deprecated
- func (s *Session) Close() error
- func (s *Session) CompareAndWrite(ctx context.Context, lun uint64, lba uint64, blocks uint8, blockSize uint32, ...) errordeprecated
- func (s *Session) Execute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*RawResult, error)deprecated
- func (s *Session) Inquiry(ctx context.Context, lun uint64) (*InquiryData, error)deprecated
- func (s *Session) LUNReset(ctx context.Context, lun uint64) (*TMFResult, error)deprecated
- func (s *Session) Logout(ctx context.Context) errordeprecated
- func (s *Session) ModeSense6(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)deprecated
- func (s *Session) ModeSense10(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)deprecated
- func (s *Session) PersistReserveIn(ctx context.Context, lun uint64, serviceAction uint8) ([]byte, error)deprecated
- func (s *Session) PersistReserveOut(ctx context.Context, lun uint64, serviceAction, scopeType uint8, ...) errordeprecated
- func (s *Session) Protocol() *ProtocolOps
- func (s *Session) Raw() *RawOps
- func (s *Session) ReadBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32) ([]byte, error)deprecated
- func (s *Session) ReadCapacity(ctx context.Context, lun uint64) (*Capacity, error)deprecated
- func (s *Session) ReportLuns(ctx context.Context) ([]uint64, error)deprecated
- func (s *Session) RequestSense(ctx context.Context, lun uint64) (*SenseInfo, error)deprecated
- func (s *Session) SCSI() *SCSIOps
- func (s *Session) SendExpStatSNConfirmation() errordeprecated
- func (s *Session) StartStopUnit(ctx context.Context, lun uint64, powerCondition uint8, start, loadEject bool) errordeprecated
- func (s *Session) StreamExecute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*StreamResult, error)deprecated
- func (s *Session) SynchronizeCache(ctx context.Context, lun uint64) errordeprecated
- func (s *Session) TMF() *TMFOps
- func (s *Session) TargetColdReset(ctx context.Context) (*TMFResult, error)deprecated
- func (s *Session) TargetWarmReset(ctx context.Context) (*TMFResult, error)deprecated
- func (s *Session) TestUnitReady(ctx context.Context, lun uint64) errordeprecated
- func (s *Session) Unmap(ctx context.Context, lun uint64, descriptors []UnmapBlockDescriptor) errordeprecated
- func (s *Session) Verify(ctx context.Context, lun uint64, lba uint64, blocks uint32) errordeprecated
- func (s *Session) WriteBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32, ...) errordeprecated
- func (s *Session) WriteSame(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32, ...) errordeprecated
- type StreamResult
- type TMFOps
- func (o *TMFOps) AbortTask(ctx context.Context, taskTag uint32) (*TMFResult, error)
- func (o *TMFOps) AbortTaskSet(ctx context.Context, lun uint64) (*TMFResult, error)
- func (o *TMFOps) ClearTaskSet(ctx context.Context, lun uint64) (*TMFResult, error)
- func (o *TMFOps) LUNReset(ctx context.Context, lun uint64) (*TMFResult, error)
- func (o *TMFOps) TargetColdReset(ctx context.Context) (*TMFResult, error)
- func (o *TMFOps) TargetWarmReset(ctx context.Context) (*TMFResult, error)
- type TMFResult
- type Target
- type TransportError
- type UnmapBlockDescriptor
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckStatus ¶ added in v1.1.2
CheckStatus inspects a SCSI status byte and optional raw sense data, returning nil for GOOD status (0x00) and a *SCSIError for anything else. This is the same interpretation that typed Session methods (Session.ReadBlocks, Session.Inquiry, etc.) apply internally.
Use this with Session.Execute or StreamResult.Wait when you want the same error-wrapping behavior without reimplementing it:
result, err := sess.Execute(ctx, lun, cdb, uiscsi.WithDataIn(256))
if err != nil { return err }
if err := uiscsi.CheckStatus(result.Status, result.SenseData); err != nil {
var se *uiscsi.SCSIError
if errors.As(err, &se) { /* se.SenseKey, se.ASC, se.ASCQ */ }
return err
}
func DecodeLUN ¶
DecodeLUN extracts the flat LUN number from an 8-byte SAM LUN encoding as returned by Session.ReportLuns. SAM-5 Section 4.6.1 defines the encoding: the first two bytes carry the address method and LUN value.
For peripheral device addressing (method 00b), the LUN is in the low 8 bits of the first two bytes. For flat space addressing (method 01b), the LUN is a 14-bit value. Other methods return the raw upper 16 bits.
func DeviceTypeName ¶
DeviceTypeName returns the short human-readable name for a SCSI peripheral device type code as found in [InquiryData.DeviceType]. The names follow the SPC-4 Table 49 convention used by lsscsi. Unknown or unmapped codes return "unknown".
Types ¶
type AsyncEvent ¶
type AsyncEvent struct {
EventCode uint8
VendorCode uint8
Parameter1 uint16
Parameter2 uint16
Parameter3 uint16
Data []byte
}
AsyncEvent carries an asynchronous event from the target.
type ExecuteOption ¶
type ExecuteOption = executeOption
ExecuteOption configures raw CDB execution.
func WithDataIn ¶
func WithDataIn(allocLen uint32) ExecuteOption
WithDataIn configures a read response of up to allocLen bytes.
func WithDataOut ¶
func WithDataOut(r io.Reader, length uint32) ExecuteOption
WithDataOut configures data to send with the command.
type InquiryData ¶
InquiryData holds a parsed INQUIRY response.
type MetricEvent ¶
type MetricEvent struct {
Type MetricEventType
OpCode uint8
Bytes uint64
Latency time.Duration
}
MetricEvent carries a single metric observation.
type MetricEventType ¶
type MetricEventType uint8
MetricEventType discriminates metric event kinds.
const ( MetricPDUSent MetricEventType = MetricEventType(session.MetricPDUSent) MetricPDUReceived MetricEventType = MetricEventType(session.MetricPDUReceived) MetricCommandComplete MetricEventType = MetricEventType(session.MetricCommandComplete) MetricBytesIn MetricEventType = MetricEventType(session.MetricBytesIn) MetricBytesOut MetricEventType = MetricEventType(session.MetricBytesOut) )
Metric event type constants, mirroring internal session values.
type Option ¶
type Option func(*dialConfig)
Option configures a Dial or Discover call via the functional options pattern.
func WithAsyncHandler ¶
func WithAsyncHandler(h func(context.Context, AsyncEvent)) Option
WithAsyncHandler registers an async event callback.
func WithCHAP ¶
WithCHAP enables CHAP authentication.
Example ¶
package main
import (
"context"
"github.com/rkujawa/uiscsi"
)
func main() {
ctx := context.Background()
_, _ = uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
uiscsi.WithCHAP("initiator-user", "s3cret"),
)
}
Output:
func WithDataDigest ¶
WithDataDigest sets data digest preferences.
func WithDigestByteOrder ¶
WithDigestByteOrder sets the byte order for CRC32C digest values on the wire. Default is LittleEndian (matches Linux LIO target). Set to binary.BigEndian for targets that use network byte order for digests.
func WithFirstBurstLength ¶ added in v1.3.0
WithFirstBurstLength sets the maximum unsolicited Data-Out size for write operations. Default is 65536 (64KB). Data up to this size is sent immediately with the SCSI Command PDU, without waiting for an R2T.
func WithHeaderDigest ¶
WithHeaderDigest sets header digest preferences.
func WithInitiatorName ¶
WithInitiatorName sets the initiator IQN.
func WithKeepaliveInterval ¶
WithKeepaliveInterval sets the keepalive ping interval.
func WithKeepaliveTimeout ¶
WithKeepaliveTimeout sets the keepalive timeout.
func WithLogger ¶
WithLogger sets the slog.Logger for both session and login diagnostics.
Example ¶
package main
import (
"context"
"log/slog"
"os"
"github.com/rkujawa/uiscsi"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}))
ctx := context.Background()
_, _ = uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
uiscsi.WithLogger(logger),
)
}
Output:
func WithMaxBurstLength ¶ added in v1.3.0
WithMaxBurstLength sets the maximum data burst size for solicited Data-Out transfers (write operations). Default is 262144 (256KB). Increasing this allows larger write bursts per R2T, reducing R2T round-trips for large writes.
func WithMaxReconnectAttempts ¶
WithMaxReconnectAttempts sets the maximum number of ERL 0 reconnect attempts.
func WithMaxRecvDataSegmentLength ¶ added in v1.3.0
WithMaxRecvDataSegmentLength sets the maximum data segment size (in bytes) that the initiator is willing to receive per PDU. The target uses this to limit Data-In PDU sizes. Default is 8192 (8KB).
For high-throughput workloads (tape drives, large block I/O), increasing this to 65536 (64KB) or 262144 (256KB) significantly reduces per-PDU overhead and improves streaming performance. The value must be between 512 and 16777215 per RFC 7143.
This controls the initiator's declared value. The target independently declares its own MaxRecvDataSegmentLength (limiting Data-Out PDU sizes from the initiator). Both directions are negotiated independently.
func WithMetricsHook ¶
func WithMetricsHook(h func(MetricEvent)) Option
WithMetricsHook registers a metrics callback.
func WithMutualCHAP ¶
WithMutualCHAP enables mutual CHAP authentication.
func WithOperationalOverrides ¶
WithOperationalOverrides overrides login negotiation parameters. Keys must match RFC 7143 Section 13 key names exactly (e.g., "InitialR2T", "ImmediateData", "MaxBurstLength", "ErrorRecoveryLevel"). Values replace the defaults proposed during login negotiation.
func WithPDUHook ¶
func WithPDUHook(h func(context.Context, PDUDirection, []byte)) Option
WithPDUHook registers a PDU send/receive hook. The []byte argument is the concatenation of BHS (48 bytes) + DataSegment from the internal transport.RawPDU. This avoids exposing internal transport types.
func WithReconnectBackoff ¶
WithReconnectBackoff sets the reconnect backoff duration.
func WithRouterBufDepth ¶ added in v1.3.0
WithRouterBufDepth sets the PDU dispatch buffer depth per task. Higher values absorb read pump stalls. Default is 64 slots.
func WithSNACKTimeout ¶
WithSNACKTimeout sets the timeout for SNACK-based PDU retransmission at ERL >= 1. When no Data-In arrives within this duration, a Status SNACK is sent to request the missing response (tail loss recovery). Default is 5 seconds.
func WithStreamBufDepth ¶ added in v1.3.0
WithStreamBufDepth sets the streaming Data-In buffer depth (number of PDU chunks buffered in the chanReader channel). Higher values absorb consumer stalls without triggering TCP backpressure — critical for tape drives that stop streaming on any TCP stall. Default is 128 slots.
type PDUDirection ¶
type PDUDirection uint8
PDUDirection indicates whether a PDU was sent or received.
const ( PDUSend PDUDirection = PDUDirection(session.PDUSend) PDUReceive PDUDirection = PDUDirection(session.PDUReceive) )
PDU direction constants, mirroring internal session values.
type ProtocolOps ¶ added in v1.2.0
type ProtocolOps struct {
// contains filtered or unexported fields
}
ProtocolOps provides low-level iSCSI protocol methods. Obtain via Session.Protocol.
Most callers should use Session.Close for session teardown. These methods are for implementors who need explicit control over RFC 7143 PDU exchanges.
func (*ProtocolOps) Logout ¶ added in v1.2.0
func (o *ProtocolOps) Logout(ctx context.Context) error
Logout performs a graceful session logout. It waits for in-flight commands to complete, then exchanges Logout/LogoutResp PDUs with the target before shutting down. Per RFC 7143 Section 11.14. Most callers should use Session.Close instead, which calls Logout internally.
func (*ProtocolOps) SendExpStatSNConfirmation ¶ added in v1.2.0
func (o *ProtocolOps) SendExpStatSNConfirmation() error
SendExpStatSNConfirmation sends a NOP-Out that confirms ExpStatSN to the target without expecting a response. Per RFC 7143 Section 11.18: ITT=0xFFFFFFFF (no response), TTT=0xFFFFFFFF, Immediate=true. CmdSN is carried but NOT advanced. This is an advanced operation; most callers do not need it.
type RawOps ¶ added in v1.2.0
type RawOps struct {
// contains filtered or unexported fields
}
RawOps provides raw CDB pass-through methods. Obtain via Session.Raw.
Unlike the typed methods on SCSIOps, raw methods do NOT interpret the SCSI status. CHECK CONDITION (0x02) is returned as-is in [RawResult.Status] or via StreamResult.Wait. Use CheckStatus or ParseSenseData for convenience.
func (*RawOps) Execute ¶ added in v1.2.0
func (o *RawOps) Execute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*RawResult, error)
Execute sends a raw CDB to the target and returns the buffered result. The entire response is read into [RawResult.Data] as []byte. For high-throughput streaming, use RawOps.StreamExecute instead.
func (*RawOps) StreamExecute ¶ added in v1.2.0
func (o *RawOps) StreamExecute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*StreamResult, error)
StreamExecute sends a raw CDB and returns a streaming result. Response data is delivered via [StreamResult.Data] as an io.Reader with bounded memory (~64KB). Call StreamResult.Wait after consuming Data to retrieve the final SCSI status and sense data.
type SCSIOps ¶ added in v1.2.0
type SCSIOps struct {
// contains filtered or unexported fields
}
SCSIOps provides typed SCSI command methods. Obtain via Session.SCSI.
func (*SCSIOps) CompareAndWrite ¶ added in v1.2.0
func (o *SCSIOps) CompareAndWrite(ctx context.Context, lun uint64, lba uint64, blocks uint8, blockSize uint32, data []byte) error
CompareAndWrite performs an atomic read-compare-write operation.
func (*SCSIOps) Inquiry ¶ added in v1.2.0
Inquiry sends a standard INQUIRY command and returns the parsed response.
func (*SCSIOps) ModeSelect6 ¶ added in v1.2.0
ModeSelect6 sends a MODE SELECT(6) command with the given parameter data. The data must include the mode parameter header, block descriptor(s), and any mode pages. PF (Page Format) bit is set automatically.
func (*SCSIOps) ModeSelect10 ¶ added in v1.2.0
ModeSelect10 sends a MODE SELECT(10) command with the given parameter data.
func (*SCSIOps) ModeSense6 ¶ added in v1.2.0
func (o *SCSIOps) ModeSense6(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)
ModeSense6 sends a MODE SENSE(6) command and returns the raw mode page bytes.
func (*SCSIOps) ModeSense10 ¶ added in v1.2.0
func (o *SCSIOps) ModeSense10(ctx context.Context, lun uint64, pageCode, subPageCode uint8) ([]byte, error)
ModeSense10 sends a MODE SENSE(10) command and returns the raw mode page bytes.
func (*SCSIOps) PersistReserveIn ¶ added in v1.2.0
func (o *SCSIOps) PersistReserveIn(ctx context.Context, lun uint64, serviceAction uint8) ([]byte, error)
PersistReserveIn sends a PERSISTENT RESERVE IN command and returns the raw response.
func (*SCSIOps) PersistReserveOut ¶ added in v1.2.0
func (o *SCSIOps) PersistReserveOut(ctx context.Context, lun uint64, serviceAction, scopeType uint8, key, saKey uint64) error
PersistReserveOut sends a PERSISTENT RESERVE OUT command.
func (*SCSIOps) ReadBlocks ¶ added in v1.2.0
func (o *SCSIOps) ReadBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32) ([]byte, error)
ReadBlocks reads blocks from the target using READ(16).
func (*SCSIOps) ReadCapacity ¶ added in v1.2.0
ReadCapacity returns the capacity of the specified LUN using READ CAPACITY(16) with fallback to READ CAPACITY(10).
func (*SCSIOps) ReportLuns ¶ added in v1.2.0
ReportLuns returns all LUNs reported by the target.
func (*SCSIOps) RequestSense ¶ added in v1.2.0
RequestSense sends a REQUEST SENSE command and returns the parsed sense data.
func (*SCSIOps) StartStopUnit ¶ added in v1.2.0
func (o *SCSIOps) StartStopUnit(ctx context.Context, lun uint64, powerCondition uint8, start, loadEject bool) error
StartStopUnit sends a START STOP UNIT command.
func (*SCSIOps) SynchronizeCache ¶ added in v1.2.0
SynchronizeCache flushes the target's volatile cache for the entire LUN.
func (*SCSIOps) TestUnitReady ¶ added in v1.2.0
TestUnitReady checks whether the specified LUN is ready.
func (*SCSIOps) Unmap ¶ added in v1.2.0
Unmap deallocates the specified LBA ranges (thin provisioning).
func (*SCSIOps) Verify ¶ added in v1.2.0
Verify requests the target to verify the specified LBA range.
type SenseInfo ¶
type SenseInfo struct {
Key uint8
ASC uint8
ASCQ uint8
Description string
Filemark bool
EOM bool
ILI bool
}
SenseInfo holds parsed sense data.
func ParseSenseData ¶ added in v1.1.2
ParseSenseData parses raw SCSI sense bytes (as returned in [RawResult.SenseData] or StreamResult.Wait) into a SenseInfo. Returns nil, nil if data is empty. Returns an error if the sense format is unrecognizable.
This is the same parser used internally by the typed Session methods. It supports both fixed (0x70/0x71) and descriptor (0x72/0x73) formats per SPC-4 Section 4.5.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session represents an active iSCSI session. It wraps the internal session and provides grouped APIs for SCSI commands, task management, raw CDB pass-through, and protocol operations.
Use the accessor methods to access each API group:
sess.SCSI() — typed SCSI commands (Inquiry, ReadBlocks, ModeSelect, etc.) sess.TMF() — task management (AbortTask, LUNReset, etc.) sess.Raw() — raw CDB pass-through (Execute, StreamExecute) sess.Protocol() — low-level iSCSI protocol (Logout, SendExpStatSNConfirmation)
func Dial ¶
Dial connects to an iSCSI target at addr, performs login negotiation, and returns a Session ready for SCSI commands. The caller must call Session.Close when done.
Example ¶
package main
import (
"context"
"fmt"
"github.com/rkujawa/uiscsi"
)
func main() {
ctx := context.Background()
sess, err := uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
)
if err != nil {
fmt.Println("dial:", err)
return
}
defer sess.Close()
fmt.Println("connected")
}
Output:
func (*Session) Execute
deprecated
func (s *Session) Execute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*RawResult, error)
Deprecated: Use sess.Raw().Execute.
Example ¶
package main
import (
"context"
"fmt"
"github.com/rkujawa/uiscsi"
)
func main() {
// Raw CDB pass-through: TEST UNIT READY.
ctx := context.Background()
sess, err := uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
)
if err != nil {
return
}
defer sess.Close()
turCDB := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // TEST UNIT READY
result, err := sess.Execute(ctx, 0, turCDB)
if err != nil {
fmt.Println("execute:", err)
return
}
fmt.Printf("status: 0x%02X\n", result.Status)
}
Output:
func (*Session) Protocol ¶ added in v1.2.0
func (s *Session) Protocol() *ProtocolOps
Protocol returns the low-level iSCSI protocol interface.
func (*Session) ReadBlocks
deprecated
func (s *Session) ReadBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32) ([]byte, error)
Deprecated: Use sess.SCSI().ReadBlocks.
Example ¶
package main
import (
"context"
"fmt"
"github.com/rkujawa/uiscsi"
)
func main() {
ctx := context.Background()
sess, err := uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
)
if err != nil {
return
}
defer sess.Close()
data, err := sess.ReadBlocks(ctx, 0, 0, 1, 512)
if err != nil {
fmt.Println("read:", err)
return
}
fmt.Printf("read %d bytes\n", len(data))
}
Output:
func (*Session) SendExpStatSNConfirmation
deprecated
func (*Session) StreamExecute
deprecated
added in
v1.1.2
func (s *Session) StreamExecute(ctx context.Context, lun uint64, cdb []byte, opts ...ExecuteOption) (*StreamResult, error)
Deprecated: Use sess.Raw().StreamExecute.
func (*Session) WriteBlocks
deprecated
func (s *Session) WriteBlocks(ctx context.Context, lun uint64, lba uint64, blocks uint32, blockSize uint32, data []byte) error
Deprecated: Use sess.SCSI().WriteBlocks.
Example ¶
package main
import (
"context"
"fmt"
"github.com/rkujawa/uiscsi"
)
func main() {
// Show write + readback verification pattern.
ctx := context.Background()
sess, err := uiscsi.Dial(ctx, "192.168.1.100:3260",
uiscsi.WithTarget("iqn.2026-03.com.example:storage"),
)
if err != nil {
return
}
defer sess.Close()
data := make([]byte, 512)
copy(data, []byte("hello iSCSI"))
if err := sess.WriteBlocks(ctx, 0, 0, 1, 512, data); err != nil {
fmt.Println("write:", err)
}
}
Output:
type StreamResult ¶ added in v1.1.2
type StreamResult struct {
// Data streams the SCSI read response as PDUs arrive from the target.
// Nil for non-read commands. Must be fully consumed before calling Wait.
Data io.Reader
// contains filtered or unexported fields
}
StreamResult carries the outcome of a streaming raw SCSI command via Session.StreamExecute. Unlike RawResult, Data is an io.Reader that streams the response as PDUs arrive, without buffering the entire response into []byte. This is critical for high-throughput sequential devices (tape drives, etc.) where large blocks (256KB–4MB) at sustained rates (400+ MB/s) make double-buffering expensive.
Memory usage is bounded to a small number of PDU-sized chunks regardless of the total transfer size (typically ~64KB with default negotiated parameters).
The caller must fully consume Data (or drain to io.Discard), then call StreamResult.Wait to retrieve the final SCSI status and sense data.
Usage:
sr, err := session.StreamExecute(ctx, lun, cdb, uiscsi.WithDataIn(blockSize))
if err != nil { ... }
_, err = io.Copy(dst, sr.Data) // stream data
status, sense, err := sr.Wait() // get final status
func (*StreamResult) Wait ¶ added in v1.1.2
func (sr *StreamResult) Wait() (status uint8, senseData []byte, err error)
Wait blocks until the SCSI command completes and returns the final status and sense data. The caller should fully consume (or discard) Data before calling Wait; otherwise Wait may block indefinitely due to flow-control backpressure. If the transport fails mid-transfer, Data.Read returns the error, and Wait returns it as well.
type TMFOps ¶ added in v1.2.0
type TMFOps struct {
// contains filtered or unexported fields
}
TMFOps provides task management function methods. Obtain via Session.TMF.
func (*TMFOps) AbortTask ¶ added in v1.2.0
AbortTask aborts a single task identified by its initiator task tag.
func (*TMFOps) AbortTaskSet ¶ added in v1.2.0
AbortTaskSet aborts all tasks on the specified LUN.
func (*TMFOps) ClearTaskSet ¶ added in v1.2.0
ClearTaskSet clears all tasks on the specified LUN.
func (*TMFOps) TargetColdReset ¶ added in v1.2.0
TargetColdReset performs a target cold reset.
type TMFResult ¶
type TMFResult struct {
Response uint8
}
TMFResult carries a task management function outcome.
type Target ¶
Target represents a discovered iSCSI target.
func Discover ¶
Discover performs a SendTargets discovery against the iSCSI target at addr. It dials, performs a Discovery session login, issues SendTargets, logs out, and returns the discovered targets.
Example ¶
package main
import (
"context"
"fmt"
"github.com/rkujawa/uiscsi"
)
func main() {
ctx := context.Background()
targets, err := uiscsi.Discover(ctx, "192.168.1.100:3260")
if err != nil {
fmt.Println("discover:", err)
return
}
for _, t := range targets {
fmt.Printf("target: %s (%d portals)\n", t.Name, len(t.Portals))
}
}
Output:
type TransportError ¶
type TransportError struct {
Op string // "dial", "login", "submit", "read", etc.
Err error // underlying error
}
TransportError represents an iSCSI transport/connection failure.
func (*TransportError) Error ¶
func (e *TransportError) Error() string
Error returns a human-readable description of the transport error.
func (*TransportError) Unwrap ¶
func (e *TransportError) Unwrap() error
Unwrap returns the underlying error, enabling errors.As/errors.Is chains.
type UnmapBlockDescriptor ¶
UnmapBlockDescriptor describes a single LBA range to deallocate.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
discover-read
command
Command discover-read demonstrates iSCSI target discovery followed by login, capacity query, and block read.
|
Command discover-read demonstrates iSCSI target discovery followed by login, capacity query, and block read. |
|
error-handling
command
Command error-handling demonstrates typed error handling and recovery patterns with the uiscsi library.
|
Command error-handling demonstrates typed error handling and recovery patterns with the uiscsi library. |
|
raw-cdb
command
Command raw-cdb demonstrates sending raw SCSI CDBs via the Execute pass-through API for custom or vendor-specific SCSI commands.
|
Command raw-cdb demonstrates sending raw SCSI CDBs via the Execute pass-through API for custom or vendor-specific SCSI commands. |
|
write-verify
command
Command write-verify demonstrates writing blocks to an iSCSI target and reading them back to verify correctness.
|
Command write-verify demonstrates writing blocks to an iSCSI target and reading them back to verify correctness. |
|
internal
|
|
|
digest
Package digest provides CRC32C digest computation for iSCSI header and data digests as specified in RFC 7143 Section 12.1.
|
Package digest provides CRC32C digest computation for iSCSI header and data digests as specified in RFC 7143 Section 12.1. |
|
login
Package login implements iSCSI login phase authentication and negotiation.
|
Package login implements iSCSI login phase authentication and negotiation. |
|
pdu
Package pdu provides iSCSI PDU encoding, decoding, and helpers.
|
Package pdu provides iSCSI PDU encoding, decoding, and helpers. |
|
scsi
Package scsi constructs SCSI Command Descriptor Blocks (CDBs) and parses responses for standard SCSI commands per SPC-4 and SBC-3.
|
Package scsi constructs SCSI Command Descriptor Blocks (CDBs) and parses responses for standard SCSI commands per SPC-4 and SBC-3. |
|
serial
Package serial implements RFC 1982 serial number arithmetic for iSCSI sequence number comparisons.
|
Package serial implements RFC 1982 serial number arithmetic for iSCSI sequence number comparisons. |
|
session
Package session implements the iSCSI session layer: command dispatch, CmdSN flow control, Data-In reassembly, and session lifecycle management per RFC 7143.
|
Package session implements the iSCSI session layer: command dispatch, CmdSN flow control, Data-In reassembly, and session lifecycle management per RFC 7143. |
|
transport
Package transport implements the iSCSI TCP transport layer: connection management, PDU framing over TCP streams, concurrent read/write pumps, ITT-based response routing, and buffer pool management.
|
Package transport implements the iSCSI TCP transport layer: connection management, PDU framing over TCP streams, concurrent read/write pumps, ITT-based response routing, and buffer pool management. |
|
Package test provides an in-process mock iSCSI target for testing.
|
Package test provides an in-process mock iSCSI target for testing. |
|
pducapture
Package pducapture provides a PDU capture framework for iSCSI test assertions.
|
Package pducapture provides a PDU capture framework for iSCSI test assertions. |