From 2eae07c7aacea352f05167eb4fd96efb686d2a56 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 29 Sep 2026 19:52:03 +0300 Subject: [PATCH] storage/fstree: Replace `O_DSYNC` with `fdatasync()` in `InitWrite()` 8ae3abe1e2f62fed3f0bc8cd32b08e17d773244e made ReplicateV2 server to call `os.File.Write()` for FSTree's file multiple times. Since the file was previously opened with `O_DSYNC` flag, each write also made sync. More writes, more syncs. For example, Put performance tests showed degradation on mid- and large-size objects (4M and 64M in particular). This improves Linux server behavior by replacing open sync flag with deferred sync syscall. Same test runs showed results pretty close (a bit worse) to Replicate. At the same time, using ReplicateV2 uses less RAM. Refs #4157. Signed-off-by: Leonard Lyubich --- CHANGELOG.md | 2 +- .../blobstor/fstree/fstree_write_linux.go | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fcbe875d..899d4a8fe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ Changelog for NeoFS Node ### Added - Online FSTree layout reshaping via the `blobstor.allow_depth_change` configuration option (#4149, #4179) -- SN now serves `ReplicateV2` API (#4168, #4164) +- SN now serves `ReplicateV2` API (#4168, #4164, #4201) - Container SN now uses `ReplicateV2` API in PUT handler when available (#4168, #4196) - `neofs-adm fschain netmap` command to fetch current and historical network maps (#4181) - Container revisions support (#4183, #4195, #4197) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index 3434201882..2fcc5f7613 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -224,6 +224,9 @@ func (x *linuxFileWriteStream) Close() error { } fd := x.fd x.fd = -1 + if err := unix.Fdatasync(fd); err != nil { + return convertLinuxError(err) + } err := linuxLinkatAndClose(fd, x.targetPath) return convertLinuxError(err) } @@ -238,7 +241,7 @@ func (x *linuxFileWriteStream) abort() { } func (w *linuxWriter) initWriteData(filePath string) (io.WriteCloser, func(), error) { - fd, err := w.openFile() + fd, err := w.openFile(w.bFlags) if err != nil { return nil, nil, convertLinuxError(err) } @@ -299,7 +302,7 @@ func (w *linuxWriter) writeCombinedFile(id oid.ID, p string, data []byte) error } func (w *linuxWriter) writeFile(p string, data []byte) error { - fd, err := w.openFile() + fd, err := w.openFile(w.flags) if err != nil { return err } @@ -310,8 +313,8 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { return linuxLinkatAndClose(fd, p) } -func (w *linuxWriter) openFile() (int, error) { - fd, err := unix.Open(w.root, w.flags, w.perm) +func (w *linuxWriter) openFile(mode int) (int, error) { + fd, err := unix.Open(w.root, mode, w.perm) if err != nil { return 0, fmt.Errorf("unix open: %w", err) }