mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-25 17:34:28 +00:00
Phase 1: Extent-mapped block storage engine with WAL, crash recovery, dirty map, flusher, and group commit. 174 tests, zero SeaweedFS imports. Phase 2: Pure Go iSCSI target (RFC 7143) with PDU codec, login negotiation, SendTargets discovery, 12 SCSI opcodes, Data-In/Out/R2T sequencing, session management, and standalone iscsi-target binary. 164 tests. IQN->BlockDevice binding via DeviceLookup interface. Total: 338 tests, 14.6K lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
39 lines
1.2 KiB
Go
39 lines
1.2 KiB
Go
package blockvol
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
var (
|
|
ErrLBAOutOfBounds = errors.New("blockvol: LBA out of bounds")
|
|
ErrWritePastEnd = errors.New("blockvol: write extends past volume end")
|
|
ErrAlignment = errors.New("blockvol: data length not aligned to block size")
|
|
)
|
|
|
|
// ValidateLBA checks that lba is within the volume's logical address space.
|
|
func ValidateLBA(lba uint64, volumeSize uint64, blockSize uint32) error {
|
|
maxLBA := volumeSize / uint64(blockSize)
|
|
if lba >= maxLBA {
|
|
return fmt.Errorf("%w: lba=%d, max=%d", ErrLBAOutOfBounds, lba, maxLBA-1)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidateWrite checks that a write at lba with dataLen bytes fits within
|
|
// the volume and that dataLen is aligned to blockSize.
|
|
func ValidateWrite(lba uint64, dataLen uint32, volumeSize uint64, blockSize uint32) error {
|
|
if err := ValidateLBA(lba, volumeSize, blockSize); err != nil {
|
|
return err
|
|
}
|
|
if dataLen%blockSize != 0 {
|
|
return fmt.Errorf("%w: dataLen=%d, blockSize=%d", ErrAlignment, dataLen, blockSize)
|
|
}
|
|
blocksNeeded := uint64(dataLen / blockSize)
|
|
maxLBA := volumeSize / uint64(blockSize)
|
|
if lba+blocksNeeded > maxLBA {
|
|
return fmt.Errorf("%w: lba=%d, blocks=%d, max=%d", ErrWritePastEnd, lba, blocksNeeded, maxLBA)
|
|
}
|
|
return nil
|
|
}
|