From 53c85c2cd79dc2edc77aee2af5e552ded0865b5e Mon Sep 17 00:00:00 2001 From: Neil Twigg Date: Thu, 29 Aug 2024 15:14:09 +0100 Subject: [PATCH] NRG: Always write term/vote and peer state synchronously Signed-off-by: Neil Twigg --- server/filestore.go | 16 ++++++++++++---- server/raft.go | 20 +++----------------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/server/filestore.go b/server/filestore.go index f5117b0fa9..11661cacec 100644 --- a/server/filestore.go +++ b/server/filestore.go @@ -9834,14 +9834,22 @@ func (alg StoreCompression) Decompress(buf []byte) ([]byte, error) { // sets O_SYNC on the open file if SyncAlways is set. The dios semaphore is // handled automatically by this function, so don't wrap calls to it in dios. func (fs *fileStore) writeFileWithOptionalSync(name string, data []byte, perm fs.FileMode) error { + if fs.fcfg.SyncAlways { + return writeFileWithSync(name, data, perm) + } <-dios defer func() { dios <- struct{}{} }() - flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC - if fs.fcfg.SyncAlways { - flags |= os.O_SYNC - } + return os.WriteFile(name, data, perm) +} + +func writeFileWithSync(name string, data []byte, perm fs.FileMode) error { + <-dios + defer func() { + dios <- struct{}{} + }() + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_SYNC f, err := os.OpenFile(name, flags, perm) if err != nil { return err diff --git a/server/raft.go b/server/raft.go index 9fbb76fefb..f911aba974 100644 --- a/server/raft.go +++ b/server/raft.go @@ -1165,11 +1165,7 @@ func (n *raft) installSnapshot(snap *snapshot) error { sn := fmt.Sprintf(snapFileT, snap.lastTerm, snap.lastIndex) sfile := filepath.Join(snapDir, sn) - <-dios - err := os.WriteFile(sfile, n.encodeSnapshot(snap), defaultFilePerms) - dios <- struct{}{} - - if err != nil { + if err := writeFileWithSync(sfile, n.encodeSnapshot(snap), defaultFilePerms); err != nil { // We could set write err here, but if this is a temporary situation, too many open files etc. // we want to retry and snapshots are not fatal. return err @@ -3874,12 +3870,7 @@ func writePeerState(sd string, ps *peerState) error { if _, err := os.Stat(psf); err != nil && !os.IsNotExist(err) { return err } - - <-dios - err := os.WriteFile(psf, encodePeerState(ps), defaultFilePerms) - dios <- struct{}{} - - return err + return writeFileWithSync(psf, encodePeerState(ps), defaultFilePerms) } func readPeerState(sd string) (ps *peerState, err error) { @@ -3903,12 +3894,7 @@ func writeTermVote(sd string, wtv []byte) error { if _, err := os.Stat(psf); err != nil && !os.IsNotExist(err) { return err } - - <-dios - err := os.WriteFile(psf, wtv, defaultFilePerms) - dios <- struct{}{} - - return err + return writeFileWithSync(psf, wtv, defaultFilePerms) } // readTermVote will read the largest term and who we voted from to stable storage.