1
0
mirror of https://github.com/facebook/rocksdb.git synced 2026-10-23 08:09:02 +03:00
Files
rocksdb/db/db_impl
Anand Ananthabhotla a3b0f187ff Add FileSystem::IsPreallocationSupported() to skip WAL truncation on open (#15395)
Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/15395

**Why the change is required:**
During `DB::Open`, RocksDB reopens the last WAL file and truncates it to its logical size. This is done even when every column family's log number has already advanced past that WAL, so the file is obsolete and will be deleted later in the same open. The only purpose of the truncation is to release space preallocated beyond the logical end of file (e.g. by `fallocate` with `FALLOC_FL_KEEP_SIZE`); `GetFileSize()` reports the apparent size, so truncating to it can only free preallocated blocks. On a FileSystem that never preallocates, this work is pure overhead: a `GetFileSize`, a `ReopenWritableFile`, a no-op `Truncate` (the default `FSWritableFile::Truncate` returns OK without doing anything), and a `Close` on every open. On remote or append-oriented FileSystems the reopen can be expensive.

**Previous behavior:**
- If recovery flushed all data, or the WALs contained no data (including when all WALs are older than the min log number to keep), `MaybeFlushFinalMemtableOrRestoreActiveLogFiles()` always called `GetLogSizeAndMaybeTruncate()` on the last WAL. In read-only mode it still issued a `GetFileSize()` whose result was discarded.
- With `avoid_flush_during_recovery`, `RestoreAliveLogFiles()` always reopened and truncated the last live WAL.

**New behavior:**
A FileSystem can report that it never preallocates space by returning false from the new `FileSystem::IsPreallocationSupported()`. When it does, DB open skips reopening and truncating the WAL. In the flushed / no-data path it also skips the unused `GetFileSize()`, so no I/O is issued against the old WAL. The read-only no-data path no longer issues the discarded `GetFileSize()` either.

**Implementation:**
- `include/rocksdb/file_system.h`: new `virtual bool IsPreallocationSupported()`, defaulting to `true`. `FileSystemWrapper` forwards it to the target.
- The policy lives in the two callers in `db_impl_open.cc`; `GetLogSizeAndMaybeTruncate()` is unchanged. `RestoreAliveLogFiles()` still calls `GetFileSize()` because the size is needed for `alive_wal_files_` and `wals_total_size_`.

**Safety, compatibility, and limitations:**
- The default is `true`, so every existing FileSystem, including ones that override `SupportedOps()` without calling the base class, keeps the current behavior. This is why it is a separate virtual function instead of an opt-in `FSSupportedOps` bit, which would silently disable truncation for those FileSystems.
- No built-in FileSystem overrides the default: Posix, Windows, `MockFileSystem`, and `LegacyFileSystemWrapper` all report `true`, so their WAL truncation behavior is unchanged. Posix deliberately reports `true` even in builds without `ROCKSDB_FALLOCATE_PRESENT`: WALs may have been preallocated by a different build running on the same machine, and a build-dependent answer would leave that space unreclaimed.
- The function describes what the FileSystem can do, not per-file options such as `allow_fallocate` or build configuration. A WAL may have been preallocated by an earlier process with different options, so gating on the current options could leak space.
- A FileSystem that wrongly returns false can only leak preallocated space, in archived WALs (`WAL_ttl_seconds` / `WAL_size_limit_MB`) or across a crash loop before obsolete WALs are deleted. Data is unaffected.

Reviewed By: joshkang97

Differential Revision: D125049741

fbshipit-source-id: ac9795f2045c46911cd86b8faacef5aa49043496
2026-10-16 12:15:57 -07:00
..