diff --git a/doc/files.md b/doc/files.md index b738d6055a2..3732a7d24a5 100644 --- a/doc/files.md +++ b/doc/files.md @@ -16,6 +16,8 @@ - [Legacy subdirectories and files](#legacy-subdirectories-and-files) +- [Filesystem recommendations](#filesystem-recommendations) + - [Notes](#notes) ## Data directory location @@ -123,6 +125,12 @@ Path | Description | Repository notes `addr.dat` | Peer IP address BDB database; replaced by `peers.dat` in [0.7.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.7.0.md) | [PR #1198](https://github.com/bitcoin/bitcoin/pull/1198), [`928d3a01`](https://github.com/bitcoin/bitcoin/commit/928d3a011cc66c7f907c4d053f674ea77dc611cc) `onion_private_key` | Cached Tor onion service private key for `-listenonion` option. Was used for Tor v2 services; replaced by `onion_v3_private_key` in [0.21.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.21.0.md) | [PR #19954](https://github.com/bitcoin/bitcoin/pull/19954) +## Filesystem recommendations + +When choosing a filesystem for the data directory (`datadir`) or blocks directory (`blocksdir`), some filesystems should be avoided: + +- **MacOS**: The exFAT filesystem should not be used. There have been multiple reports of database corruption when using exFAT on MacOS for Bitcoin Core. This appears to be due to filesystem-level issues with exFAT on MacOS. See [Issue #31454](https://github.com/bitcoin/bitcoin/issues/31454) for more details. + ## Notes 1. The `/` (slash, U+002F) is used as the platform-independent path component separator in this document. diff --git a/src/common/init.cpp b/src/common/init.cpp index 5a704404689..812a781c5ae 100644 --- a/src/common/init.cpp +++ b/src/common/init.cpp @@ -6,8 +6,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -62,6 +64,35 @@ std::optional InitConfig(ArgsManager& args, SettingsAbortFn setting fs::create_directories(net_path / "wallets"); } + // Warn if we are trying to put the datadir on an exFAT fs on MacOS + // This is an upstream issue known to cause bugs, see #28552 +#ifdef __APPLE__ + struct PathCheck { + fs::path path; + std::string_view description; + }; + std::array paths_to_check{{ + {args.GetDataDirNet(), "data directory"}, + {args.GetBlocksDirPath(), "blocks directory"} + }}; + for (const auto& check : paths_to_check) { + FSType fs_type = GetFilesystemType(check.path); + switch(fs_type) { + case FSType::EXFAT: + InitWarning(strprintf(_("Specified %s \"%s\" is exFAT which is known to have intermittent corruption problems on MacOS. " + "See https://github.com/bitcoin/bitcoin/blob/master/doc/files.md#filesystem-recommendations for more information."), + check.description, + fs::PathToString(check.path))); + break; + case FSType::ERROR: + LogInfo("Failed to detect filesystem type of %s: %s\n", check.description, fs::PathToString(check.path)); + break; + default: + break; + } + } +#endif + // Show an error or warn/log if there is a bitcoin.conf file in the // datadir that is being ignored. const fs::path base_config_path = base_path / BITCOIN_CONF_FILENAME; diff --git a/src/util/fs_helpers.cpp b/src/util/fs_helpers.cpp index 4d06afe1442..6bf417bb46b 100644 --- a/src/util/fs_helpers.cpp +++ b/src/util/fs_helpers.cpp @@ -41,6 +41,10 @@ #include /* For SHGetSpecialFolderPathW */ #endif // WIN32 +#ifdef __APPLE__ +#include +#endif + /** Mutex to protect dir_locks. */ static GlobalMutex cs_dir_locks; /** A map that contains all the currently held directory locks. After @@ -309,3 +313,17 @@ std::optional InterpretPermString(const std::string& s) return std::nullopt; } } + +#ifdef __APPLE__ +FSType GetFilesystemType(const fs::path& path) { + struct statfs fs_info; + if (statfs(path.c_str(), &fs_info) != 0) { + return FSType::ERROR; + } + + if (strcmp(fs_info.f_fstypename, "exfat") == 0) { + return FSType::EXFAT; + } + return FSType::OTHER; +} +#endif diff --git a/src/util/fs_helpers.h b/src/util/fs_helpers.h index 28dd6d979d5..7423da82a42 100644 --- a/src/util/fs_helpers.h +++ b/src/util/fs_helpers.h @@ -14,6 +14,23 @@ #include #include +#ifdef __APPLE__ +enum class FSType { + EXFAT, + OTHER, + ERROR +}; + +/** + * Detect filesystem type for a given path. + * Currently identifies exFAT filesystems which cause issues on MacOS. + * + * @param[in] path The directory path to check + * @return FSType enum indicating the filesystem type + */ +FSType GetFilesystemType(const fs::path& path); +#endif + /** * Ensure file contents are fully committed to disk, using a platform-specific * feature analogous to fsync().