fault_injection_fs.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright 2014 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. // This test uses a custom FileSystem to keep track of the state of a file
  10. // system the last "Sync". The data being written is cached in a "buffer".
  11. // Only when "Sync" is called, the data will be persistent. It can similate
  12. // file data loss (or entire files) not protected by a "Sync". For any of the
  13. // FileSystem related operations, by specify the "IOStatus Error", a specific
  14. // error can be returned when file system is not activated.
  15. #pragma once
  16. #include <algorithm>
  17. #include <map>
  18. #include <set>
  19. #include <string>
  20. #include "file/filename.h"
  21. #include "rocksdb/file_system.h"
  22. #include "util/mutexlock.h"
  23. #include "util/random.h"
  24. #include "util/thread_local.h"
  25. namespace ROCKSDB_NAMESPACE {
  26. class TestFSWritableFile;
  27. class FaultInjectionTestFS;
  28. enum class FaultInjectionIOType {
  29. kRead = 0,
  30. kWrite,
  31. kMetadataRead,
  32. kMetadataWrite,
  33. };
  34. struct FSFileState {
  35. std::string filename_;
  36. uint64_t pos_at_last_append_ = 0;
  37. uint64_t pos_at_last_sync_ = 0;
  38. std::string buffer_;
  39. explicit FSFileState(const std::string& filename = {})
  40. : filename_(filename) {}
  41. bool IsFullySynced() const {
  42. return pos_at_last_append_ == pos_at_last_sync_;
  43. }
  44. IOStatus DropUnsyncedData();
  45. IOStatus DropRandomUnsyncedData(Random* rand);
  46. };
  47. // A wrapper around WritableFileWriter* file
  48. // is written to or sync'ed.
  49. class TestFSWritableFile : public FSWritableFile {
  50. public:
  51. explicit TestFSWritableFile(const std::string& fname,
  52. const FileOptions& file_opts,
  53. std::unique_ptr<FSWritableFile>&& f,
  54. FaultInjectionTestFS* fs);
  55. virtual ~TestFSWritableFile();
  56. IOStatus Append(const Slice& data, const IOOptions&,
  57. IODebugContext*) override;
  58. IOStatus Append(const Slice& data, const IOOptions& options,
  59. const DataVerificationInfo& verification_info,
  60. IODebugContext* dbg) override;
  61. IOStatus Truncate(uint64_t size, const IOOptions& options,
  62. IODebugContext* dbg) override;
  63. IOStatus Close(const IOOptions& options, IODebugContext* dbg) override;
  64. IOStatus Flush(const IOOptions&, IODebugContext*) override;
  65. IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override;
  66. IOStatus RangeSync(uint64_t /*offset*/, uint64_t /*nbytes*/,
  67. const IOOptions& options, IODebugContext* dbg) override;
  68. bool IsSyncThreadSafe() const override { return true; }
  69. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  70. const IOOptions& options,
  71. IODebugContext* dbg) override;
  72. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  73. const IOOptions& options,
  74. const DataVerificationInfo& verification_info,
  75. IODebugContext* dbg) override;
  76. size_t GetRequiredBufferAlignment() const override {
  77. return target_->GetRequiredBufferAlignment();
  78. }
  79. bool use_direct_io() const override { return target_->use_direct_io(); }
  80. uint64_t GetFileSize(const IOOptions& options, IODebugContext* dbg) override {
  81. MutexLock l(&mutex_);
  82. return target_->GetFileSize(options, dbg);
  83. }
  84. private:
  85. FSFileState state_; // Need protection by mutex_
  86. FileOptions file_opts_;
  87. std::unique_ptr<FSWritableFile> target_;
  88. bool writable_file_opened_;
  89. FaultInjectionTestFS* fs_;
  90. port::Mutex mutex_;
  91. const bool unsync_data_loss_;
  92. };
  93. // A wrapper around FSRandomRWFile* file
  94. // is read from/write to or sync'ed.
  95. class TestFSRandomRWFile : public FSRandomRWFile {
  96. public:
  97. explicit TestFSRandomRWFile(const std::string& fname,
  98. std::unique_ptr<FSRandomRWFile>&& f,
  99. FaultInjectionTestFS* fs);
  100. virtual ~TestFSRandomRWFile();
  101. IOStatus Write(uint64_t offset, const Slice& data, const IOOptions& options,
  102. IODebugContext* dbg) override;
  103. IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
  104. Slice* result, char* scratch,
  105. IODebugContext* dbg) const override;
  106. IOStatus Close(const IOOptions& options, IODebugContext* dbg) override;
  107. IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override;
  108. IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override;
  109. size_t GetRequiredBufferAlignment() const override {
  110. return target_->GetRequiredBufferAlignment();
  111. }
  112. bool use_direct_io() const override { return target_->use_direct_io(); }
  113. private:
  114. // keep a copy of file name, so we can untrack it in File system, when it is
  115. // closed
  116. std::string fname_;
  117. std::unique_ptr<FSRandomRWFile> target_;
  118. bool file_opened_;
  119. FaultInjectionTestFS* fs_;
  120. };
  121. class TestFSRandomAccessFile : public FSRandomAccessFile {
  122. public:
  123. explicit TestFSRandomAccessFile(const std::string& fname,
  124. std::unique_ptr<FSRandomAccessFile>&& f,
  125. FaultInjectionTestFS* fs);
  126. ~TestFSRandomAccessFile() override {}
  127. IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
  128. Slice* result, char* scratch,
  129. IODebugContext* dbg) const override;
  130. IOStatus ReadAsync(FSReadRequest& req, const IOOptions& opts,
  131. std::function<void(FSReadRequest&, void*)> cb,
  132. void* cb_arg, void** io_handle, IOHandleDeleter* del_fn,
  133. IODebugContext* dbg) override;
  134. IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs,
  135. const IOOptions& options, IODebugContext* dbg) override;
  136. size_t GetRequiredBufferAlignment() const override {
  137. return target_->GetRequiredBufferAlignment();
  138. }
  139. bool use_direct_io() const override { return target_->use_direct_io(); }
  140. size_t GetUniqueId(char* id, size_t max_size) const override;
  141. IOStatus GetFileSize(uint64_t* file_size) override;
  142. private:
  143. std::unique_ptr<FSRandomAccessFile> target_;
  144. FaultInjectionTestFS* fs_;
  145. const bool is_sst_;
  146. };
  147. class TestFSSequentialFile : public FSSequentialFileOwnerWrapper {
  148. public:
  149. explicit TestFSSequentialFile(std::unique_ptr<FSSequentialFile>&& f,
  150. FaultInjectionTestFS* fs, std::string fname)
  151. : FSSequentialFileOwnerWrapper(std::move(f)),
  152. fs_(fs),
  153. fname_(std::move(fname)) {}
  154. IOStatus Read(size_t n, const IOOptions& options, Slice* result,
  155. char* scratch, IODebugContext* dbg) override;
  156. IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options,
  157. Slice* result, char* scratch,
  158. IODebugContext* dbg) override;
  159. private:
  160. FaultInjectionTestFS* fs_;
  161. std::string fname_;
  162. uint64_t read_pos_ = 0;
  163. uint64_t target_read_pos_ = 0;
  164. };
  165. class TestFSDirectory : public FSDirectory {
  166. public:
  167. explicit TestFSDirectory(FaultInjectionTestFS* fs, std::string dirname,
  168. FSDirectory* dir)
  169. : fs_(fs), dirname_(std::move(dirname)), dir_(dir) {}
  170. ~TestFSDirectory() {}
  171. IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override;
  172. IOStatus Close(const IOOptions& options, IODebugContext* dbg) override;
  173. IOStatus FsyncWithDirOptions(
  174. const IOOptions& options, IODebugContext* dbg,
  175. const DirFsyncOptions& dir_fsync_options) override;
  176. private:
  177. FaultInjectionTestFS* fs_;
  178. std::string dirname_;
  179. std::unique_ptr<FSDirectory> dir_;
  180. };
  181. class FaultInjectionTestFS : public FileSystemWrapper {
  182. public:
  183. explicit FaultInjectionTestFS(const std::shared_ptr<FileSystem>& base)
  184. : FileSystemWrapper(base),
  185. filesystem_active_(true),
  186. filesystem_writable_(false),
  187. inject_unsynced_data_loss_(false),
  188. read_unsynced_data_(true),
  189. allow_link_open_file_(false),
  190. injected_thread_local_read_error_(DeleteThreadLocalErrorContext),
  191. injected_thread_local_write_error_(DeleteThreadLocalErrorContext),
  192. injected_thread_local_metadata_read_error_(
  193. DeleteThreadLocalErrorContext),
  194. injected_thread_local_metadata_write_error_(
  195. DeleteThreadLocalErrorContext),
  196. ingest_data_corruption_before_write_(false),
  197. checksum_handoff_func_type_(kCRC32c) {}
  198. virtual ~FaultInjectionTestFS() override { fs_error_.PermitUncheckedError(); }
  199. static const char* kClassName() { return "FaultInjectionTestFS"; }
  200. const char* Name() const override { return kClassName(); }
  201. static bool IsInjectedError(const Status& s,
  202. const std::string& specific_error_marker = "") {
  203. if (s.ok()) {
  204. return false;
  205. }
  206. const char* state = s.getState();
  207. if (state == nullptr) {
  208. return false;
  209. }
  210. bool is_injected_error = std::strstr(state, kInjected.c_str()) != nullptr;
  211. bool is_specific_error =
  212. specific_error_marker.empty() ||
  213. std::strstr(state, specific_error_marker.c_str()) != nullptr;
  214. return is_injected_error && is_specific_error;
  215. }
  216. static bool IsFailedToWriteToWALError(const Status& s) {
  217. return IsInjectedError(s, kFailedToWriteToWAL);
  218. }
  219. IOStatus NewDirectory(const std::string& name, const IOOptions& options,
  220. std::unique_ptr<FSDirectory>* result,
  221. IODebugContext* dbg) override;
  222. IOStatus FileExists(const std::string& fname, const IOOptions& options,
  223. IODebugContext* dbg) override;
  224. IOStatus GetChildren(const std::string& dir, const IOOptions& options,
  225. std::vector<std::string>* result,
  226. IODebugContext* dbg) override;
  227. IOStatus GetChildrenFileAttributes(const std::string& dir,
  228. const IOOptions& options,
  229. std::vector<FileAttributes>* result,
  230. IODebugContext* dbg) override;
  231. IOStatus NewWritableFile(const std::string& fname,
  232. const FileOptions& file_opts,
  233. std::unique_ptr<FSWritableFile>* result,
  234. IODebugContext* dbg) override;
  235. IOStatus ReopenWritableFile(const std::string& fname,
  236. const FileOptions& file_opts,
  237. std::unique_ptr<FSWritableFile>* result,
  238. IODebugContext* dbg) override;
  239. IOStatus ReuseWritableFile(const std::string& fname,
  240. const std::string& old_fname,
  241. const FileOptions& file_opts,
  242. std::unique_ptr<FSWritableFile>* result,
  243. IODebugContext* dbg) override;
  244. IOStatus NewRandomRWFile(const std::string& fname,
  245. const FileOptions& file_opts,
  246. std::unique_ptr<FSRandomRWFile>* result,
  247. IODebugContext* dbg) override;
  248. IOStatus NewRandomAccessFile(const std::string& fname,
  249. const FileOptions& file_opts,
  250. std::unique_ptr<FSRandomAccessFile>* result,
  251. IODebugContext* dbg) override;
  252. IOStatus NewSequentialFile(const std::string& f, const FileOptions& file_opts,
  253. std::unique_ptr<FSSequentialFile>* r,
  254. IODebugContext* dbg) override;
  255. IOStatus DeleteFile(const std::string& f, const IOOptions& options,
  256. IODebugContext* dbg) override;
  257. IOStatus GetFileSize(const std::string& f, const IOOptions& options,
  258. uint64_t* file_size, IODebugContext* dbg) override;
  259. IOStatus GetFileModificationTime(const std::string& fname,
  260. const IOOptions& options,
  261. uint64_t* file_mtime,
  262. IODebugContext* dbg) override;
  263. IOStatus RenameFile(const std::string& s, const std::string& t,
  264. const IOOptions& options, IODebugContext* dbg) override;
  265. IOStatus LinkFile(const std::string& src, const std::string& target,
  266. const IOOptions& options, IODebugContext* dbg) override;
  267. IOStatus NumFileLinks(const std::string& fname, const IOOptions& options,
  268. uint64_t* count, IODebugContext* dbg) override;
  269. IOStatus AreFilesSame(const std::string& first, const std::string& second,
  270. const IOOptions& options, bool* res,
  271. IODebugContext* dbg) override;
  272. IOStatus GetAbsolutePath(const std::string& db_path, const IOOptions& options,
  273. std::string* output_path,
  274. IODebugContext* dbg) override;
  275. // Undef to eliminate clash on Windows
  276. #undef GetFreeSpace
  277. IOStatus GetFreeSpace(const std::string& path, const IOOptions& options,
  278. uint64_t* disk_free, IODebugContext* dbg) override {
  279. IOStatus io_s;
  280. if (!IsFilesystemActive() &&
  281. fs_error_.subcode() == IOStatus::SubCode::kNoSpace) {
  282. *disk_free = 0;
  283. } else {
  284. io_s = MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead,
  285. options);
  286. if (io_s.ok()) {
  287. io_s = target()->GetFreeSpace(path, options, disk_free, dbg);
  288. }
  289. }
  290. return io_s;
  291. }
  292. IOStatus IsDirectory(const std::string& path, const IOOptions& options,
  293. bool* is_dir, IODebugContext* dgb) override;
  294. IOStatus Poll(std::vector<void*>& io_handles,
  295. size_t min_completions) override;
  296. IOStatus AbortIO(std::vector<void*>& io_handles) override;
  297. void WritableFileClosed(const FSFileState& state);
  298. void WritableFileSynced(const FSFileState& state);
  299. void WritableFileAppended(const FSFileState& state);
  300. void RandomRWFileClosed(const std::string& fname);
  301. IOStatus DropUnsyncedFileData();
  302. IOStatus DropRandomUnsyncedFileData(Random* rnd);
  303. IOStatus DeleteFilesCreatedAfterLastDirSync(const IOOptions& options,
  304. IODebugContext* dbg);
  305. void ResetState();
  306. void UntrackFile(const std::string& f);
  307. void SyncDir(const std::string& dirname) {
  308. MutexLock l(&mutex_);
  309. dir_to_new_files_since_last_sync_.erase(dirname);
  310. }
  311. // Setting the filesystem to inactive is the test equivalent to simulating a
  312. // system reset. Setting to inactive will freeze our saved filesystem state so
  313. // that it will stop being recorded. It can then be reset back to the state at
  314. // the time of the reset.
  315. bool IsFilesystemActive() {
  316. MutexLock l(&mutex_);
  317. return filesystem_active_;
  318. }
  319. // Setting filesystem_writable_ makes NewWritableFile. ReopenWritableFile,
  320. // and NewRandomRWFile bypass FaultInjectionTestFS and go directly to the
  321. // target FS
  322. bool IsFilesystemDirectWritable() {
  323. MutexLock l(&mutex_);
  324. return filesystem_writable_;
  325. }
  326. void SetFilesystemActiveNoLock(
  327. bool active, IOStatus error = IOStatus::Corruption("Not active")) {
  328. error.PermitUncheckedError();
  329. filesystem_active_ = active;
  330. if (!active) {
  331. fs_error_ = error;
  332. }
  333. }
  334. void SetFilesystemActive(
  335. bool active, IOStatus error = IOStatus::Corruption("Not active")) {
  336. MutexLock l(&mutex_);
  337. error.PermitUncheckedError();
  338. SetFilesystemActiveNoLock(active, error);
  339. }
  340. void SetFilesystemDirectWritable(bool writable) {
  341. MutexLock l(&mutex_);
  342. filesystem_writable_ = writable;
  343. }
  344. // If true, we buffer write data in memory to simulate data loss upon system
  345. // crash by only having process crashes
  346. void SetInjectUnsyncedDataLoss(bool inject) {
  347. MutexLock l(&mutex_);
  348. inject_unsynced_data_loss_ = inject;
  349. }
  350. bool InjectUnsyncedDataLoss() {
  351. MutexLock l(&mutex_);
  352. return inject_unsynced_data_loss_;
  353. }
  354. // In places (e.g. GetSortedWals()) RocksDB relies on querying the file size
  355. // or even reading the contents of files currently open for writing, and
  356. // as in POSIX semantics, expects to see the flushed size and contents
  357. // regardless of what has been synced. FaultInjectionTestFS historically
  358. // did not emulate this behavior, only showing synced data from such read
  359. // operations. (Different from FaultInjectionTestEnv--sigh.) Calling this
  360. // function with false restores this historical behavior for testing
  361. // stability, but use of this semantics must be phased out as it is
  362. // inconsistent with expected FileSystem semantics. In other words, this
  363. // functionality is DEPRECATED. Intended to be set after construction and
  364. // unchanged (not thread safe).
  365. void SetReadUnsyncedData(bool read_unsynced_data) {
  366. read_unsynced_data_ = read_unsynced_data;
  367. }
  368. bool ReadUnsyncedData() const { return read_unsynced_data_; }
  369. // FaultInjectionTestFS normally includes a hygiene check for FileSystem
  370. // implementations that only support LinkFile() on closed files (not open
  371. // for write). Setting this to true bypasses the check.
  372. void SetAllowLinkOpenFile(bool allow_link_open_file = true) {
  373. allow_link_open_file_ = allow_link_open_file;
  374. }
  375. bool ShouldIOActivitiesExcludedFromFaultInjection(
  376. Env::IOActivity io_activity) {
  377. MutexLock l(&mutex_);
  378. return io_activities_excluded_from_fault_injection.find(io_activity) !=
  379. io_activities_excluded_from_fault_injection.end();
  380. }
  381. void AssertNoOpenFile() { assert(open_managed_files_.empty()); }
  382. IOStatus GetError() { return fs_error_; }
  383. void SetFileSystemIOError(IOStatus io_error) {
  384. MutexLock l(&mutex_);
  385. io_error.PermitUncheckedError();
  386. fs_error_ = io_error;
  387. }
  388. // To simulate the data corruption before data is written in FS
  389. void IngestDataCorruptionBeforeWrite() {
  390. MutexLock l(&mutex_);
  391. ingest_data_corruption_before_write_ = true;
  392. }
  393. void NoDataCorruptionBeforeWrite() {
  394. MutexLock l(&mutex_);
  395. ingest_data_corruption_before_write_ = false;
  396. }
  397. bool ShouldDataCorruptionBeforeWrite() {
  398. MutexLock l(&mutex_);
  399. return ingest_data_corruption_before_write_;
  400. }
  401. void SetChecksumHandoffFuncType(const ChecksumType& func_type) {
  402. MutexLock l(&mutex_);
  403. checksum_handoff_func_type_ = func_type;
  404. }
  405. const ChecksumType& GetChecksumHandoffFuncType() {
  406. MutexLock l(&mutex_);
  407. return checksum_handoff_func_type_;
  408. }
  409. void SetFailGetUniqueId(bool flag) {
  410. MutexLock l(&mutex_);
  411. fail_get_file_unique_id_ = flag;
  412. }
  413. bool ShouldFailGetUniqueId() {
  414. MutexLock l(&mutex_);
  415. return fail_get_file_unique_id_;
  416. }
  417. void SetFailRandomAccessGetFileSizeSst(bool flag) {
  418. MutexLock l(&mutex_);
  419. fail_random_access_get_file_size_sst_ = flag;
  420. }
  421. bool ShouldFailRandomAccessGetFileSizeSst() {
  422. MutexLock l(&mutex_);
  423. return fail_random_access_get_file_size_sst_;
  424. }
  425. void SetFailFilesystemGetFileSizeSst(bool flag) {
  426. MutexLock l(&mutex_);
  427. fail_fs_get_file_size_sst_ = flag;
  428. }
  429. bool ShouldFailFilesystemGetFileSizeSst() {
  430. MutexLock l(&mutex_);
  431. return fail_fs_get_file_size_sst_;
  432. }
  433. // Specify what the operation, so we can inject the right type of error
  434. enum ErrorOperation : char {
  435. kRead = 0,
  436. kMultiReadSingleReq = 1,
  437. kMultiRead = 2,
  438. kOpen,
  439. kAppend,
  440. kPositionedAppend,
  441. kUnknown,
  442. };
  443. void SetThreadLocalErrorContext(FaultInjectionIOType type, uint32_t seed,
  444. int one_in, bool retryable,
  445. bool has_data_loss) {
  446. struct ErrorContext* new_ctx = new ErrorContext(seed);
  447. new_ctx->one_in = one_in;
  448. new_ctx->count = 0;
  449. new_ctx->retryable = retryable;
  450. new_ctx->has_data_loss = has_data_loss;
  451. SetErrorContextOfFaultInjectionIOType(type, new_ctx);
  452. }
  453. static void DeleteThreadLocalErrorContext(void* p) {
  454. ErrorContext* ctx = static_cast<ErrorContext*>(p);
  455. delete ctx;
  456. }
  457. IOStatus MaybeInjectThreadLocalError(
  458. FaultInjectionIOType type, const IOOptions& io_options,
  459. const std::string& file_name = "", ErrorOperation op = kUnknown,
  460. Slice* slice = nullptr, bool direct_io = false, char* scratch = nullptr,
  461. bool need_count_increase = false, bool* fault_injected = nullptr);
  462. int GetAndResetInjectedThreadLocalErrorCount(FaultInjectionIOType type) {
  463. ErrorContext* ctx = GetErrorContextFromFaultInjectionIOType(type);
  464. int count = 0;
  465. if (ctx) {
  466. count = ctx->count;
  467. ctx->count = 0;
  468. }
  469. return count;
  470. }
  471. void SetIOActivitiesExcludedFromFaultInjection(
  472. const std::set<Env::IOActivity>& io_activities) {
  473. MutexLock l(&mutex_);
  474. io_activities_excluded_from_fault_injection = io_activities;
  475. }
  476. void SetFileTypesExcludedFromWriteFaultInjection(
  477. const std::set<FileType>& types) {
  478. MutexLock l(&mutex_);
  479. file_types_excluded_from_write_fault_injection_ = types;
  480. }
  481. void EnableThreadLocalErrorInjection(FaultInjectionIOType type) {
  482. ErrorContext* ctx = GetErrorContextFromFaultInjectionIOType(type);
  483. if (ctx) {
  484. ctx->enable_error_injection = true;
  485. }
  486. }
  487. void EnableAllThreadLocalErrorInjection() {
  488. EnableThreadLocalErrorInjection(FaultInjectionIOType::kRead);
  489. EnableThreadLocalErrorInjection(FaultInjectionIOType::kWrite);
  490. EnableThreadLocalErrorInjection(FaultInjectionIOType::kMetadataRead);
  491. EnableThreadLocalErrorInjection(FaultInjectionIOType::kMetadataWrite);
  492. }
  493. void DisableThreadLocalErrorInjection(FaultInjectionIOType type) {
  494. ErrorContext* ctx = GetErrorContextFromFaultInjectionIOType(type);
  495. if (ctx) {
  496. ctx->enable_error_injection = false;
  497. }
  498. }
  499. void DisableAllThreadLocalErrorInjection() {
  500. DisableThreadLocalErrorInjection(FaultInjectionIOType::kRead);
  501. DisableThreadLocalErrorInjection(FaultInjectionIOType::kWrite);
  502. DisableThreadLocalErrorInjection(FaultInjectionIOType::kMetadataRead);
  503. DisableThreadLocalErrorInjection(FaultInjectionIOType::kMetadataWrite);
  504. }
  505. void PrintInjectedThreadLocalErrorBacktrace(FaultInjectionIOType type);
  506. // If there is unsynced data in the specified file within the specified
  507. // range [offset, offset + n), return the unsynced data overlapping with
  508. // that range, in a corresponding range of scratch. When known, also return
  509. // the position of the last sync, so that the caller can determine whether
  510. // more data is available from the target file when not available from
  511. // unsynced.
  512. void ReadUnsynced(const std::string& fname, uint64_t offset, size_t n,
  513. Slice* result, char* scratch, int64_t* pos_at_last_sync);
  514. inline static const std::string kInjected = "injected";
  515. private:
  516. inline static const std::string kFailedToWriteToWAL =
  517. "failed to write to WAL";
  518. port::Mutex mutex_;
  519. std::map<std::string, FSFileState> db_file_state_;
  520. std::set<std::string> open_managed_files_;
  521. // directory -> (file name -> file contents to recover)
  522. // When data is recovered from unsyned parent directory, the files with
  523. // empty file contents to recover is deleted. Those with non-empty ones
  524. // will be recovered to content accordingly.
  525. std::unordered_map<std::string, std::map<std::string, std::string>>
  526. dir_to_new_files_since_last_sync_;
  527. bool filesystem_active_; // Record flushes, syncs, writes
  528. bool filesystem_writable_; // Bypass FaultInjectionTestFS and go directly
  529. // to underlying FS for writable files
  530. bool inject_unsynced_data_loss_; // See InjectUnsyncedDataLoss()
  531. bool read_unsynced_data_; // See SetReadUnsyncedData()
  532. bool allow_link_open_file_; // See SetAllowLinkOpenFile()
  533. IOStatus fs_error_;
  534. enum ErrorType : int {
  535. kErrorTypeStatus = 0,
  536. kErrorTypeCorruption,
  537. kErrorTypeTruncated,
  538. kErrorTypeMax
  539. };
  540. struct ErrorContext {
  541. Random rand;
  542. int one_in;
  543. int count;
  544. bool enable_error_injection;
  545. void* callstack;
  546. std::string message;
  547. int frames;
  548. ErrorType type;
  549. bool retryable;
  550. bool has_data_loss;
  551. explicit ErrorContext(uint32_t seed)
  552. : rand(seed),
  553. enable_error_injection(false),
  554. callstack(nullptr),
  555. frames(0),
  556. retryable(false),
  557. has_data_loss(false) {}
  558. ~ErrorContext() {
  559. if (callstack) {
  560. free(callstack);
  561. }
  562. }
  563. };
  564. std::set<FileType> file_types_excluded_from_write_fault_injection_;
  565. std::set<Env::IOActivity> io_activities_excluded_from_fault_injection;
  566. ThreadLocalPtr injected_thread_local_read_error_;
  567. ThreadLocalPtr injected_thread_local_write_error_;
  568. ThreadLocalPtr injected_thread_local_metadata_read_error_;
  569. ThreadLocalPtr injected_thread_local_metadata_write_error_;
  570. bool ingest_data_corruption_before_write_;
  571. ChecksumType checksum_handoff_func_type_;
  572. bool fail_get_file_unique_id_ = false;
  573. bool fail_random_access_get_file_size_sst_ = false;
  574. bool fail_fs_get_file_size_sst_ = false;
  575. // Inject an error. For a READ operation, a status of IOError(), a
  576. // corruption in the contents of scratch, or truncation of slice
  577. // are the types of error with equal probability. For OPEN,
  578. // its always an IOError.
  579. // fault_injected returns whether a fault is injected. It is needed
  580. // because some fault is inected with IOStatus to be OK.
  581. IOStatus MaybeInjectThreadLocalReadError(const IOOptions& io_options,
  582. ErrorOperation op, Slice* slice,
  583. bool direct_io, char* scratch,
  584. bool need_count_increase,
  585. bool* fault_injected);
  586. bool ShouldExcludeFromWriteFaultInjection(const std::string& file_name) {
  587. MutexLock l(&mutex_);
  588. FileType file_type = kTempFile;
  589. uint64_t file_number = 0;
  590. if (!TryParseFileName(file_name, &file_number, &file_type)) {
  591. return false;
  592. }
  593. return file_types_excluded_from_write_fault_injection_.find(file_type) !=
  594. file_types_excluded_from_write_fault_injection_.end();
  595. }
  596. // Extract number of type from file name. Return false if failing to fine
  597. // them.
  598. bool TryParseFileName(const std::string& file_name, uint64_t* number,
  599. FileType* type);
  600. ErrorContext* GetErrorContextFromFaultInjectionIOType(
  601. FaultInjectionIOType type) {
  602. ErrorContext* ctx = nullptr;
  603. switch (type) {
  604. case FaultInjectionIOType::kRead:
  605. ctx = static_cast<struct ErrorContext*>(
  606. injected_thread_local_read_error_.Get());
  607. break;
  608. case FaultInjectionIOType::kWrite:
  609. ctx = static_cast<struct ErrorContext*>(
  610. injected_thread_local_write_error_.Get());
  611. break;
  612. case FaultInjectionIOType::kMetadataRead:
  613. ctx = static_cast<struct ErrorContext*>(
  614. injected_thread_local_metadata_read_error_.Get());
  615. break;
  616. case FaultInjectionIOType::kMetadataWrite:
  617. ctx = static_cast<struct ErrorContext*>(
  618. injected_thread_local_metadata_write_error_.Get());
  619. break;
  620. default:
  621. assert(false);
  622. break;
  623. }
  624. return ctx;
  625. }
  626. void SetErrorContextOfFaultInjectionIOType(FaultInjectionIOType type,
  627. ErrorContext* new_ctx) {
  628. ErrorContext* old_ctx = nullptr;
  629. switch (type) {
  630. case FaultInjectionIOType::kRead:
  631. old_ctx = static_cast<struct ErrorContext*>(
  632. injected_thread_local_read_error_.Swap(new_ctx));
  633. break;
  634. case FaultInjectionIOType::kWrite:
  635. old_ctx = static_cast<struct ErrorContext*>(
  636. injected_thread_local_write_error_.Swap(new_ctx));
  637. break;
  638. case FaultInjectionIOType::kMetadataRead:
  639. old_ctx = static_cast<struct ErrorContext*>(
  640. injected_thread_local_metadata_read_error_.Swap(new_ctx));
  641. break;
  642. case FaultInjectionIOType::kMetadataWrite:
  643. old_ctx = static_cast<struct ErrorContext*>(
  644. injected_thread_local_metadata_write_error_.Swap(new_ctx));
  645. break;
  646. default:
  647. assert(false);
  648. break;
  649. }
  650. if (old_ctx) {
  651. DeleteThreadLocalErrorContext(old_ctx);
  652. }
  653. }
  654. std::string GetErrorMessage(FaultInjectionIOType type,
  655. const std::string& file_name, ErrorOperation op) {
  656. std::ostringstream msg;
  657. msg << kInjected << " ";
  658. switch (type) {
  659. case FaultInjectionIOType::kRead:
  660. msg << "read error";
  661. break;
  662. case FaultInjectionIOType::kWrite:
  663. msg << "write error";
  664. break;
  665. case FaultInjectionIOType::kMetadataRead:
  666. msg << "metadata read error";
  667. break;
  668. case FaultInjectionIOType::kMetadataWrite:
  669. msg << "metadata write error";
  670. break;
  671. default:
  672. assert(false);
  673. break;
  674. }
  675. if (type == FaultInjectionIOType::kWrite &&
  676. (op == ErrorOperation::kOpen || op == ErrorOperation::kAppend ||
  677. op == ErrorOperation::kPositionedAppend)) {
  678. FileType file_type = kTempFile;
  679. uint64_t ignore = 0;
  680. if (TryParseFileName(file_name, &ignore, &file_type) &&
  681. file_type == FileType::kWalFile) {
  682. msg << " " << kFailedToWriteToWAL;
  683. }
  684. }
  685. return msg.str();
  686. }
  687. };
  688. } // namespace ROCKSDB_NAMESPACE