From 6c9d2a7e876d954c77f3726336b39669ea3d91f0 Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Wed, 7 Sep 2016 16:40:33 -0700 Subject: [PATCH] wal: fsync directory after wal file rename Fixes #6368 --- wal/wal.go | 15 ++++++++++++--- wal/wal_unix.go | 7 +++++++ wal/wal_windows.go | 8 ++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/wal/wal.go b/wal/wal.go index 13193c064a40..ea6be505594e 100644 --- a/wal/wal.go +++ b/wal/wal.go @@ -69,7 +69,11 @@ var ( // A just opened WAL is in read mode, and ready for reading records. // The WAL will be ready for appending after reading out all the previous records. type WAL struct { - dir string // the living directory of the underlay files + dir string // the living directory of the underlay files + + // dirFile is a fd for the wal directory for syncing on Rename + dirFile *os.File + metadata []byte // metadata recorded at the head of each WAL state raftpb.HardState // hardstate recorded at the head of WAL @@ -130,7 +134,6 @@ func Create(dirpath string, metadata []byte) (*WAL, error) { if err := w.SaveSnapshot(walpb.Snapshot{}); err != nil { return nil, err } - return w.renameWal(tmpdirpath) } @@ -373,6 +376,10 @@ func (w *WAL) cut() error { if err = os.Rename(newTail.Name(), fpath); err != nil { return err } + if err = fileutil.Fsync(w.dirFile); err != nil { + return err + } + newTail.Close() if newTail, err = fileutil.LockFile(fpath, os.O_WRONLY, fileutil.PrivateFileMode); err != nil { @@ -467,6 +474,7 @@ func (w *WAL) Close() error { return err } } + for _, l := range w.locks { if l == nil { continue @@ -475,7 +483,8 @@ func (w *WAL) Close() error { plog.Errorf("failed to unlock during closing wal: %s", err) } } - return nil + + return w.dirFile.Close() } func (w *WAL) saveEntry(e *raftpb.Entry) error { diff --git a/wal/wal_unix.go b/wal/wal_unix.go index 101ea6acc3c8..52d98458097f 100644 --- a/wal/wal_unix.go +++ b/wal/wal_unix.go @@ -34,5 +34,12 @@ func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) { } w.fp = newFilePipeline(w.dir, SegmentSizeBytes) + + df, derr := os.Open(w.dir) + if derr != nil { + return nil, derr + } + w.dirFile = df + return w, nil } diff --git a/wal/wal_windows.go b/wal/wal_windows.go index 0b9e434cf546..c12f3a349f53 100644 --- a/wal/wal_windows.go +++ b/wal/wal_windows.go @@ -37,5 +37,13 @@ func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) { newWAL.Close() return nil, err } + + // windows expects a writeable file for fsync + df, derr := os.OpenFile(w.dir, os.O_WRONLY, fileutil.PrivateFileMode) + if derr != nil { + return nil, derr + } + w.dirFile = df + return newWAL, nil }