Browse Source

wal: zero out wal tail past its first zero record

Whenever the WAL is opened for writes, it should write zeroes to its tail
starting from the first zero record. Otherwise, if there are entries past
the first zero record due to a torn write, any new writes that overlap the
old entries will lead to a garbage record on the tail and cause a CRC
mismatch.
Anthony Romano 9 years ago
parent
commit
f1ead43482
1 changed files with 12 additions and 1 deletions
  1. 12 1
      wal/wal.go

+ 12 - 1
wal/wal.go

@@ -301,6 +301,18 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.
 			state.Reset()
 			state.Reset()
 			return nil, state, nil, err
 			return nil, state, nil, err
 		}
 		}
+		// decodeRecord() will return io.EOF if it detects a zero record,
+		// but this zero record may be followed by non-zero records from
+		// a torn write. Overwriting some of these non-zero records, but
+		// not all, will cause CRC errors on WAL open. Since the records
+		// were never fully synced to disk in the first place, it's safe
+		// to zero them out to avoid any CRC errors from new writes.
+		if _, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET); err != nil {
+			return nil, state, nil, err
+		}
+		if err = fileutil.ZeroToEnd(w.tail().File); err != nil {
+			return nil, state, nil, err
+		}
 	}
 	}
 
 
 	err = nil
 	err = nil
@@ -319,7 +331,6 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.
 
 
 	if w.tail() != nil {
 	if w.tail() != nil {
 		// create encoder (chain crc with the decoder), enable appending
 		// create encoder (chain crc with the decoder), enable appending
-		_, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET)
 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC())
 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC())
 	}
 	}
 	w.decoder = nil
 	w.decoder = nil