@@ -39,13 +39,24 @@ func (n nullWriter) Write(b []byte) (int, error) {
3939
4040func (d * DrivePerf ) runReadTest (ctx context.Context , path string , data []byte ) (uint64 , error ) {
4141 startTime := time .Now ()
42- r , err := os .OpenFile (path , syscall .O_DIRECT | os .O_RDONLY , 0o400 )
42+
43+ // Choose flags based on sync mode
44+ var flags int
45+ if d .SyncMode {
46+ // Use O_SYNC for synchronized reads (for small block sizes or when --sync is specified)
47+ flags = syscall .O_SYNC | os .O_RDONLY
48+ } else {
49+ // Use O_DIRECT for direct I/O (bypasses page cache)
50+ flags = syscall .O_DIRECT | os .O_RDONLY
51+ }
52+
53+ r , err := os .OpenFile (path , flags , 0o400 )
4354 if err != nil {
4455 return 0 , err
4556 }
4657 unix .Fadvise (int (r .Fd ()), 0 , int64 (d .FileSize ), unix .FADV_SEQUENTIAL )
4758
48- n , err := copyAligned (& nullWriter {}, r , data , int64 (d .FileSize ), r .Fd ())
59+ n , err := copyAligned (& nullWriter {}, r , data , int64 (d .FileSize ), r .Fd (), d . SyncMode )
4960 r .Close ()
5061 if err != nil {
5162 return 0 , err
@@ -125,7 +136,10 @@ const DirectioAlignSize = 4096
125136// used with DIRECT I/O based file descriptor and it is expected that
126137// input writer *os.File not a generic io.Writer. Make sure to have
127138// the file opened for writes with syscall.O_DIRECT flag.
128- func copyAligned (w io.Writer , r io.Reader , alignedBuf []byte , totalSize int64 , fd uintptr ) (int64 , error ) {
139+ //
140+ // When syncMode is true, alignment checks are skipped as O_DSYNC/O_SYNC
141+ // is used instead of O_DIRECT.
142+ func copyAligned (w io.Writer , r io.Reader , alignedBuf []byte , totalSize int64 , fd uintptr , syncMode bool ) (int64 , error ) {
129143 if totalSize == 0 {
130144 return 0 , nil
131145 }
@@ -140,7 +154,8 @@ func copyAligned(w io.Writer, r io.Reader, alignedBuf []byte, totalSize int64, f
140154 }
141155 }
142156
143- if len (buf )% DirectioAlignSize != 0 {
157+ // In sync mode, we don't need to worry about alignment since we're not using O_DIRECT
158+ if ! syncMode && len (buf )% DirectioAlignSize != 0 {
144159 // Disable O_DIRECT on fd's on unaligned buffer
145160 // perform an amortized Fdatasync(fd) on the fd at
146161 // the end, this is performed by the caller before
@@ -164,8 +179,9 @@ func copyAligned(w io.Writer, r io.Reader, alignedBuf []byte, totalSize int64, f
164179 )
165180
166181 remain := len (buf ) % DirectioAlignSize
167- if remain == 0 {
168- // buf is aligned for directio write()
182+ // In sync mode, treat all buffers as "aligned" (no special handling needed)
183+ if syncMode || remain == 0 {
184+ // buf is aligned for directio write() or we're in sync mode
169185 n , err = w .Write (buf )
170186 nw = int64 (n )
171187 } else {
@@ -225,12 +241,23 @@ func (d *DrivePerf) runWriteTest(ctx context.Context, path string, data []byte)
225241 }
226242
227243 startTime := time .Now ()
228- w , err := os .OpenFile (path , syscall .O_DIRECT | os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0o600 )
244+
245+ // Choose flags based on sync mode
246+ var flags int
247+ if d .SyncMode {
248+ // Use O_DSYNC for synchronized writes (for small block sizes or when --sync is specified)
249+ flags = syscall .O_DSYNC | os .O_RDWR | os .O_CREATE | os .O_TRUNC
250+ } else {
251+ // Use O_DIRECT for direct I/O (bypasses page cache)
252+ flags = syscall .O_DIRECT | os .O_RDWR | os .O_CREATE | os .O_TRUNC
253+ }
254+
255+ w , err := os .OpenFile (path , flags , 0o600 )
229256 if err != nil {
230257 return 0 , err
231258 }
232259
233- n , err := copyAligned (w , newRandomReader (ctx ), data , int64 (d .FileSize ), w .Fd ())
260+ n , err := copyAligned (w , newRandomReader (ctx ), data , int64 (d .FileSize ), w .Fd (), d . SyncMode )
234261 if err != nil {
235262 w .Close ()
236263 return 0 , err
0 commit comments