Files
seaweedfs/weed/storage/blockvol/batchio/standard.go
T
Ping QiuandClaude Opus 4.6 66d5ba0a84 fix: BatchIO review fixes — linked SQE, ring overflow, resource leak, sync parity
1. HIGH: LinkedWriteFsync now uses SubmitLinkRequests (IOSQE_IO_LINK)
   instead of SubmitRequests, ensuring write+fdatasync execute as a
   linked chain in the kernel. Falls back to sequential on error.

2. HIGH: PreadBatch/PwriteBatch chunk ops by ring capacity to prevent
   "too many requests" rejection when dirty map exceeds ring size (256).

3. MED: CloseBatchIO() added to Flusher, called in BlockVol.Close()
   after final flush to release io_uring ring / kernel resources.

4. MED: Sync parity — both standard and io_uring paths now use
   fdatasync (via platform-specific fdatasync_linux.go / fdatasync_other.go).
   Standard path previously used fsync; now matches io_uring semantics.
   On non-Linux, fdatasync falls back to fsync (only option available).

10 batchio tests, all blockvol tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:47:03 -07:00

50 lines
1.3 KiB
Go

package batchio
import "os"
// standardBatchIO implements BatchIO with sequential os.File calls.
// This is functionally identical to calling ReadAt/WriteAt/fdatasync directly.
type standardBatchIO struct{}
// NewStandard returns a BatchIO that uses sequential pread/pwrite/fdatasync.
// This is the default (and only) implementation on non-Linux platforms.
func NewStandard() BatchIO {
return &standardBatchIO{}
}
func (s *standardBatchIO) PreadBatch(fd *os.File, ops []Op) error {
for i := range ops {
if _, err := fd.ReadAt(ops[i].Buf, ops[i].Offset); err != nil {
return err
}
}
return nil
}
func (s *standardBatchIO) PwriteBatch(fd *os.File, ops []Op) error {
for i := range ops {
if _, err := fd.WriteAt(ops[i].Buf, ops[i].Offset); err != nil {
return err
}
}
return nil
}
// Fsync issues fdatasync to flush data to disk. Uses fdatasync(2) on Linux
// for parity with the io_uring path. Falls back to fsync on other platforms.
func (s *standardBatchIO) Fsync(fd *os.File) error {
return fdatasync(fd)
}
// LinkedWriteFsync writes buf at offset then issues fdatasync, sequentially.
func (s *standardBatchIO) LinkedWriteFsync(fd *os.File, buf []byte, offset int64) error {
if _, err := fd.WriteAt(buf, offset); err != nil {
return err
}
return fdatasync(fd)
}
func (s *standardBatchIO) Close() error {
return nil
}