diff --git a/HISTORY.md b/HISTORY.md index c73d5da71..e683a0752 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -20,6 +20,7 @@ * Fixed a bug that `Iterator::Refresh()` reads stale keys after DeleteRange() performed. * Fixed a race condition when disable and re-enable manual compaction. * Fixed automatic error recovery failure in atomic flush. +* Fixed a race condition when mmaping a WritableFile on POSIX. ### Public API changes * Remove BlockBasedTableOptions.hash_index_allow_collision which already takes no effect. diff --git a/env/fs_posix.cc b/env/fs_posix.cc index 23ef89784..cd23b26a9 100644 --- a/env/fs_posix.cc +++ b/env/fs_posix.cc @@ -325,14 +325,7 @@ class PosixFileSystem : public FileSystem { SetFD_CLOEXEC(fd, &options); if (options.use_mmap_writes) { - if (!checkedDiskForMmap_) { - // this will be executed once in the program's lifetime. - // do not use mmapWrite on non ext-3/xfs/tmpfs systems. - if (!SupportsFastAllocate(fname)) { - forceMmapOff_ = true; - } - checkedDiskForMmap_ = true; - } + MaybeForceDisableMmap(fd); } if (options.use_mmap_writes && !forceMmapOff_) { result->reset(new PosixMmapFile(fname, fd, page_size_, options)); @@ -431,14 +424,7 @@ class PosixFileSystem : public FileSystem { } if (options.use_mmap_writes) { - if (!checkedDiskForMmap_) { - // this will be executed once in the program's lifetime. - // do not use mmapWrite on non ext-3/xfs/tmpfs systems. - if (!SupportsFastAllocate(fname)) { - forceMmapOff_ = true; - } - checkedDiskForMmap_ = true; - } + MaybeForceDisableMmap(fd); } if (options.use_mmap_writes && !forceMmapOff_) { result->reset(new PosixMmapFile(fname, fd, page_size_, options)); @@ -999,8 +985,7 @@ class PosixFileSystem : public FileSystem { } #endif private: - bool checkedDiskForMmap_; - bool forceMmapOff_; // do we override Env options? + bool forceMmapOff_ = false; // do we override Env options? // Returns true iff the named directory exists and is a directory. virtual bool DirExists(const std::string& dname) { @@ -1011,10 +996,10 @@ class PosixFileSystem : public FileSystem { return false; // stat() failed return false } - bool SupportsFastAllocate(const std::string& path) { + bool SupportsFastAllocate(int fd) { #ifdef ROCKSDB_FALLOCATE_PRESENT struct statfs s; - if (statfs(path.c_str(), &s)) { + if (fstatfs(fd, &s)) { return false; } switch (s.f_type) { @@ -1028,11 +1013,26 @@ class PosixFileSystem : public FileSystem { return false; } #else - (void)path; + (void)fd; return false; #endif } + void MaybeForceDisableMmap(int fd) { + static std::once_flag s_check_disk_for_mmap_once; + assert(this == FileSystem::Default().get()); + std::call_once( + s_check_disk_for_mmap_once, + [this](int fdesc) { + // this will be executed once in the program's lifetime. + // do not use mmapWrite on non ext-3/xfs/tmpfs systems. + if (!SupportsFastAllocate(fdesc)) { + forceMmapOff_ = true; + } + }, + fd); + } + #ifdef ROCKSDB_IOURING_PRESENT bool IsIOUringEnabled() { if (RocksDbIOUringEnable && RocksDbIOUringEnable()) { @@ -1166,8 +1166,7 @@ size_t PosixFileSystem::GetLogicalBlockSizeForWriteIfNeeded( } PosixFileSystem::PosixFileSystem() - : checkedDiskForMmap_(false), - forceMmapOff_(false), + : forceMmapOff_(false), page_size_(getpagesize()), allow_non_owner_access_(true) { #if defined(ROCKSDB_IOURING_PRESENT)