Skip to content

Commit

Permalink
wal: fall back to closing wal if locked dir rename fails
Browse files Browse the repository at this point in the history
Detecting windows at compile time isn't enough since etcd might be
on linux but the fs is backed by windows.

Fixes: etcd-io#8178
Fixes: etcd-io#6984
  • Loading branch information
Anthony Romano authored and visheshnp committed Aug 3, 2017
1 parent fb66343 commit 0192bbd
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 85 deletions.
42 changes: 42 additions & 0 deletions wal/wal.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,48 @@ func Create(dirpath string, metadata []byte) (*WAL, error) {
return w, nil
}

func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) {
if err := os.RemoveAll(w.dir); err != nil {
return nil, err
}
// On non-Windows platforms, hold the lock while renaming. Releasing
// the lock and trying to reacquire it quickly can be flaky because
// it's possible the process will fork to spawn a process while this is
// happening. The fds are set up as close-on-exec by the Go runtime,
// but there is a window between the fork and the exec where another
// process holds the lock.
if err := os.Rename(tmpdirpath, w.dir); err != nil {
if _, ok := err.(*os.LinkError); ok {
return w.renameWalUnlock(tmpdirpath)
}
return nil, err
}
w.fp = newFilePipeline(w.dir, SegmentSizeBytes)
df, err := fileutil.OpenDir(w.dir)
w.dirFile = df
return w, err
}

func (w *WAL) renameWalUnlock(tmpdirpath string) (*WAL, error) {
// rename of directory with locked files doesn't work on windows/cifs;
// close the WAL to release the locks so the directory can be renamed.
plog.Infof("releasing file lock to rename %q to %q", tmpdirpath, w.dir)
w.Close()
if err := os.Rename(tmpdirpath, w.dir); err != nil {
return nil, err
}
// reopen and relock
newWAL, oerr := Open(w.dir, walpb.Snapshot{})
if oerr != nil {
return nil, oerr
}
if _, _, _, err := newWAL.ReadAll(); err != nil {
newWAL.Close()
return nil, err
}
return newWAL, nil
}

// Open opens the WAL at the given snap.
// The snap SHOULD have been previously saved to the WAL, or the following
// ReadAll will fail.
Expand Down
44 changes: 0 additions & 44 deletions wal/wal_unix.go

This file was deleted.

41 changes: 0 additions & 41 deletions wal/wal_windows.go

This file was deleted.

0 comments on commit 0192bbd

Please sign in to comment.