diff --git a/README.md b/README.md index c8ecd7e..66cdc6a 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,11 @@ cd lazyfs/ ./scripts/mount-lazyfs.sh -c config/default.toml -m /tmp/lazyfs.mnt -r /tmp/lazyfs.root +# [Recommended] Running LazyFS in single-thread mode (add '-s') + +./scripts/mount-lazyfs.sh -c config/default.toml -m /tmp/lazyfs.mnt -r /tmp/lazyfs.root -s + + # Umount with ./scripts/umount-lazyfs.sh -m /tmp/lazyfs.mnt/ diff --git a/lazyfs/include/lazyfs/lazyfs.hpp b/lazyfs/include/lazyfs/lazyfs.hpp index db32c6d..da6e7f2 100644 --- a/lazyfs/include/lazyfs/lazyfs.hpp +++ b/lazyfs/include/lazyfs/lazyfs.hpp @@ -216,7 +216,7 @@ class LazyFS : public Fusepp::Fuse { * @param parts Pages to be persisted * */ - void command_fault_sync_page (string path, string parts, bool lock_needed = true); + void command_fault_sync_page (string path, string parts, bool sync_other_files, bool lock_needed = true); /** * @brief Fifo: (info) Display the cache usage diff --git a/lazyfs/src/lazyfs.cpp b/lazyfs/src/lazyfs.cpp index 94b0977..8bf0838 100644 --- a/lazyfs/src/lazyfs.cpp +++ b/lazyfs/src/lazyfs.cpp @@ -7,6 +7,7 @@ * */ +#include #include #include #include @@ -23,16 +24,14 @@ #include #include #include -#include - // LazyFS specific imports -#include #include #include #include #include #include +#include using namespace std; using namespace cache; @@ -50,7 +49,7 @@ LazyFS::LazyFS (Cache* cache, cache::config::Config* config, std::thread* faults_handler_thread, void (*fht_worker) (LazyFS* filesystem), - unordered_map>* faults) { + unordered_map>* faults) { this->FSConfig = config; this->FSCache = cache; @@ -58,7 +57,7 @@ LazyFS::LazyFS (Cache* cache, this->fht_worker = fht_worker; this->faults = faults; this->pending_write = NULL; - this->kill_before .store (false); + this->kill_before.store (false); for (auto const& it : faults::Fault::allow_crash_fs_operations) { this->crash_faults_before_map.insert ({it, {}}); @@ -68,8 +67,8 @@ LazyFS::LazyFS (Cache* cache, LazyFS::~LazyFS () {} -vector LazyFS::get_injecting_fault() { - lock_guard guard(this->injecting_fault_lock); +vector LazyFS::get_injecting_fault () { + lock_guard guard (this->injecting_fault_lock); return injecting_fault; } @@ -78,22 +77,22 @@ bool LazyFS::trigger_crash_fault (string opname, string from_op_path, string to_op_path, bool lock_needed) { - + vector> opfaults; - /* - const int length = from_op_path.length(); - // declaring character array (+1 for null terminator) - char* char_array = new char[length + 1]; - - // copying the contents of the - // string to char array - strcpy(char_array, from_op_path.c_str()); - struct stat buffer; - int status; + /* + const int length = from_op_path.length(); + // declaring character array (+1 for null terminator) + char* char_array = new char[length + 1]; - status = lstat(char_array, &buffer); -*/ + // copying the contents of the + // string to char array + strcpy(char_array, from_op_path.c_str()); + struct stat buffer; + int status; + + status = lstat(char_array, &buffer); + */ if (optiming == "before") { opfaults = this->crash_faults_before_map.at (opname); @@ -104,7 +103,8 @@ bool LazyFS::trigger_crash_fault (string opname, if (opfaults.size () > 0) { bool is_multi_path = false; - if (faults::Fault::fs_op_multi_path.find (opname) != faults::Fault::fs_op_multi_path.end ()) { + if (faults::Fault::fs_op_multi_path.find (opname) != + faults::Fault::fs_op_multi_path.end ()) { is_multi_path = true; } @@ -133,9 +133,9 @@ bool LazyFS::trigger_crash_fault (string opname, spdlog::critical ("Triggered fault condition (op={},timing={})", opname, optiming); - this->injecting_fault_lock.lock(); + this->injecting_fault_lock.lock (); this_ ()->command_unsynced_data_report (this->injecting_fault); - this->injecting_fault_lock.unlock(); + this->injecting_fault_lock.unlock (); pid_t lazyfs_pid = getpid (); spdlog::critical ("Killing LazyFS pid {}!", lazyfs_pid); @@ -146,49 +146,56 @@ bool LazyFS::trigger_crash_fault (string opname, return false; } -// TO-DO: Unify this with trigger_crash_fault. This function gets the faults in the LazyFS fault structure, and the other functions gets in the crash_faults_before_map and crash_faults_after_map. +// TO-DO: Unify this with trigger_crash_fault. This function gets the faults in the LazyFS fault +// structure, and the other functions gets in the crash_faults_before_map and +// crash_faults_after_map. bool LazyFS::trigger_configured_clear_fault (string opname, - string optiming, - string from_path, - string to_path, - bool lock_needed) { + string optiming, + string from_path, + string to_path, + bool lock_needed) { - auto it = faults->find(from_path); + auto it = faults->find (from_path); - if (it != faults->end()) { + if (it != faults->end ()) { auto& v_faults = it->second; for (auto fault : v_faults) { - faults::ClearF* clear_fault = dynamic_cast(fault); - faults::SyncPageF* page_fault = dynamic_cast(fault); + faults::ClearF* clear_fault = dynamic_cast (fault); + faults::SyncPageF* page_fault = dynamic_cast (fault); if (clear_fault && clear_fault->op == opname) { - bool is_multi_path = faults::Fault::fs_op_multi_path.find (opname) != faults::Fault::fs_op_multi_path.end (); + bool is_multi_path = faults::Fault::fs_op_multi_path.find (opname) != + faults::Fault::fs_op_multi_path.end (); if ((is_multi_path && to_path == clear_fault->to) || !is_multi_path) { - - int current_count = clear_fault->counter.load(); + + int current_count = clear_fault->counter.load (); if (optiming == "before") { - clear_fault->counter.fetch_add(1); + clear_fault->counter.fetch_add (1); current_count++; } - + if (clear_fault->timing == optiming) { if (current_count == clear_fault->occurrence) { - spdlog::critical ("Triggered fault condition (op={},timing={})", opname, optiming); + spdlog::critical ("Triggered fault condition (op={},timing={})", + opname, + optiming); - this->injecting_fault_lock.lock(); + this->injecting_fault_lock.lock (); this_ ()->command_unsynced_data_report (this->injecting_fault); - this->injecting_fault_lock.unlock(); + this->injecting_fault_lock.unlock (); if (clear_fault->crash) { - + if (optiming == "after" && clear_fault->ret) { - this_()->kill_before.store(true); - spdlog::warn("Syscall {} will return. LazyFS will crash before the next system call.", opname); + this_ ()->kill_before.store (true); + spdlog::warn ("Syscall {} will return. LazyFS will crash " + "before the next system call.", + opname); return true; } @@ -200,7 +207,7 @@ bool LazyFS::trigger_configured_clear_fault (string opname, spdlog::warn ("[lazyfs.cmds]: clearing cache..."); this_ ()->command_fault_clear_cache (lock_needed); - } + } } } } @@ -208,30 +215,38 @@ bool LazyFS::trigger_configured_clear_fault (string opname, if (page_fault && page_fault->op == opname) { - bool is_multi_path = faults::Fault::fs_op_multi_path.find (opname) != faults::Fault::fs_op_multi_path.end (); + bool is_multi_path = faults::Fault::fs_op_multi_path.find (opname) != + faults::Fault::fs_op_multi_path.end (); if ((is_multi_path && to_path == page_fault->to) || !is_multi_path) { - - int current_count = page_fault->counter.load(); + + int current_count = page_fault->counter.load (); if (optiming == "before") { - current_count = page_fault->counter.fetch_add(1); + current_count = page_fault->counter.fetch_add (1); } - + if (page_fault->timing == optiming) { if (current_count == page_fault->occurrence) { - spdlog::critical ("Triggered fault condition (op={},timing={})", opname, optiming); + spdlog::critical ("Triggered fault condition (op={},timing={})", + opname, + optiming); - this->injecting_fault_lock.lock(); + this->injecting_fault_lock.lock (); this_ ()->command_unsynced_data_report (this->injecting_fault); - this->injecting_fault_lock.unlock(); + this->injecting_fault_lock.unlock (); - this_ ()->command_fault_sync_page (from_path, page_fault->pages, lock_needed); + this_ ()->command_fault_sync_page (from_path, + page_fault->pages, + page_fault->sync_other_files, + lock_needed); if (optiming == "after" && page_fault->ret) { - this_()->kill_before.store(true); - spdlog::critical("Syscall {} will return. LazyFS will crash before the next system call.", opname); + this_ ()->kill_before.store (true); + spdlog::warn ("Syscall {} will return. LazyFS will crash before " + "the next system call.", + opname); return true; } @@ -252,7 +267,7 @@ void LazyFS::add_crash_fault (string crash_timing, string crash_regex_from, string crash_regex_to) { - //TO-DO: regex_to is not actually regex + // TO-DO: regex_to is not actually regex if (crash_timing == "before") { auto& crash_regex_list = crash_faults_before_map.at (crash_operation); @@ -280,9 +295,9 @@ void LazyFS::command_unsynced_data_report (vector paths_to_exclude) { spdlog::info ("[lazyfs.cmds]: report: all data blocks are synced!"); } else { - + spdlog::set_pattern ("[%^lazyfs.report%$] %v"); - spdlog::info("----------------------------------------------------"); + spdlog::info ("----------------------------------------------------"); size_t total_bytes_unsynced = 0; @@ -290,13 +305,16 @@ void LazyFS::command_unsynced_data_report (vector paths_to_exclude) { string ino = string (get<0> (it).c_str ()); auto files_mapped = FSCache->find_files_mapped_to_inode (ino); - + bool report = true; - if (paths_to_exclude.size() > 0) { - report = find_first_of (files_mapped.begin(), files_mapped.end(), paths_to_exclude.begin(), paths_to_exclude.end()) != files_mapped.end(); + if (paths_to_exclude.size () > 0) { + report = find_first_of (files_mapped.begin (), + files_mapped.end (), + paths_to_exclude.begin (), + paths_to_exclude.end ()) != files_mapped.end (); } - if(report) { + if (report) { if (std::get<2> (it).size () > 0 && files_mapped.size () > 0) { @@ -305,15 +323,15 @@ void LazyFS::command_unsynced_data_report (vector paths_to_exclude) { spdlog::info ("[inode {}]: files mapped to this inode:", ino); for (auto it = files_mapped.begin (); it != files_mapped.end (); ++it) - spdlog::info ("\t=> file: '{}'", - *it); + spdlog::info ("\t=> file: '{}'", *it); int last_block_index = -1; int last_block_off_start = -1; int first_block_id = -1; - for (auto block_it = std::get<2> (it).begin (); block_it != std::get<2> (it).end (); - block_it++) { + for (auto block_it = std::get<2> (it).begin (); + block_it != std::get<2> (it).end (); + block_it++) { int block_id = get<0> (*block_it); auto offs = get<1> (*block_it); @@ -326,15 +344,14 @@ void LazyFS::command_unsynced_data_report (vector paths_to_exclude) { if (block_id != (get<0> (*std::next (block_it)) - 1)) { - spdlog::info ( - "[inode {}]: (block {}) to (block " - "{}) [byte index {} to index {}]", - ino, - last_block_index, - block_id, - last_block_off_start, - (offs.second + block_id * FSConfig->IO_BLOCK_SIZE) - - (first_block_id * FSConfig->IO_BLOCK_SIZE)); + spdlog::info ("[inode {}]: (block {}) to (block " + "{}) [byte index {} to index {}]", + ino, + last_block_index, + block_id, + last_block_off_start, + (offs.second + block_id * FSConfig->IO_BLOCK_SIZE) - + (first_block_id * FSConfig->IO_BLOCK_SIZE)); last_block_off_start = offs.first; last_block_index = block_id; @@ -343,19 +360,19 @@ void LazyFS::command_unsynced_data_report (vector paths_to_exclude) { total_bytes_unsynced += get<1> (*block_it).second - get<1> (*block_it).first + 1; } - } } - spdlog::info("----------------------------------------------------"); + spdlog::info ("----------------------------------------------------"); } - spdlog::info ("Total number of bytes un-fsynced: {} bytes.",total_bytes_unsynced); + spdlog::info ("Total number of bytes un-fsynced: {} bytes.", total_bytes_unsynced); - if (paths_to_exclude.size() > 0) + if (paths_to_exclude.size () > 0) spdlog::info ("Info about un-fsynced bytes from some files was excluded."); - - spdlog::info("----------------------------------------------------"); - if (THREAD_ID) spdlog::set_pattern("[thread: %t] %+"); + + spdlog::info ("----------------------------------------------------"); + if (THREAD_ID) + spdlog::set_pattern ("[thread: %t] %+"); } } @@ -371,18 +388,58 @@ void LazyFS::command_fault_clear_cache (bool lock_needed) { spdlog::warn ("[lazyfs.cmds]: cache is cleared."); } -void LazyFS::command_fault_sync_page (string path, string parts, bool lock_needed) { +void LazyFS::command_fault_sync_page (string path, + string parts, + bool sync_other_files, + bool lock_needed) { if (lock_needed) std::unique_lock lock (cache_command_lock); - - spdlog::warn ("[lazyfs.cmds]: clear page request submitted..."); - + + spdlog::warn ("[lazyfs.{}]: sync pages request submitted...", SYNC_PAGE); + string owner (path); - FSCache->partial_file_sync (owner, const_cast(path.c_str()), parts); + bool synced = FSCache->partial_file_sync (owner, const_cast (path.c_str ()), parts); + + if (!synced) + spdlog::warn ("[lazyfs.{}]: sync pages went wrong!", SYNC_PAGE); + else { + spdlog::info ("[lazyfs.{}]: sync pages successfuly!", SYNC_PAGE); + + if (sync_other_files) { + spdlog::warn ( + "[lazyfs.{}]: sync other files is enabled, proceeding to sync other files...", + SYNC_PAGE); + vector inodes = FSCache->unsynced_inodes (); - spdlog::warn ("[lazyfs.cmds]: pages requested cleared."); + string path_inode = this_ ()->FSCache->get_original_inode (owner); + + for (const auto& inode : inodes) { + if (inode != path_inode) { + + const auto& files = FSCache->find_files_mapped_to_inode (inode); + + for (const auto& file : files) { + + synced = + FSCache->sync_owner (inode, true, const_cast (file.c_str ())); + if (!synced) { + spdlog::warn ("[lazyfs.{}]: Failed to sync file: {}", SYNC_PAGE, file); + } else { + spdlog::info ("[lazyfs.{}]: Successfully synced file: {}", + SYNC_PAGE, + file); + } + } + } + } + } + } + + spdlog::warn ("[lazyfs.cmds]: pages requested synced."); + + command_unsynced_data_report ({}); } void LazyFS::command_display_cache_usage (bool lock_needed) { @@ -405,7 +462,6 @@ void LazyFS::command_checkpoint (bool lock_needed) { spdlog::warn ("[lazyfs.cmds]: checkpoint is done."); } - /************ LazyFS FUSE operations ***************/ void* LazyFS::lfs_init (struct fuse_conn_info* conn, struct fuse_config* cfg) { @@ -420,7 +476,7 @@ void* LazyFS::lfs_init (struct fuse_conn_info* conn, struct fuse_config* cfg) { new (this_ ()->faults_handler_thread) std::thread (this_ ()->fht_worker, this_ ()); - this_ ()->print_faults(); + this_ ()->print_faults (); return this_ (); } @@ -526,7 +582,7 @@ int LazyFS::lfs_readdir (const char* path, off_t offset, struct fuse_file_info* fi, enum fuse_readdir_flags flags) { - + std::shared_lock lock (cache_command_lock); if (this_ ()->FSConfig->log_all_operations) { @@ -560,7 +616,7 @@ int LazyFS::lfs_readdir (const char* path, int LazyFS::lfs_open (const char* path, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("open", "before", path, ""); this_ ()->trigger_configured_clear_fault ("open", "before", path, ""); @@ -605,15 +661,15 @@ int LazyFS::lfs_open (const char* path, struct fuse_file_info* fi) { if (fi->flags & O_TRUNC) lfs_truncate (path, 0, fi); - this_()->trigger_crash_fault ("open", "after", path, "", false); - this_()->trigger_configured_clear_fault ("open", "after", path, "", false); + this_ ()->trigger_crash_fault ("open", "after", path, "", false); + this_ ()->trigger_configured_clear_fault ("open", "after", path, "", false); return 0; } int LazyFS::lfs_create (const char* path, mode_t mode, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("create", "before", path, ""); this_ ()->trigger_configured_clear_fault ("create", "before", path, ""); @@ -693,7 +749,7 @@ int LazyFS::lfs_write (const char* path, off_t offset, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("write", "before", path, ""); this_ ()->trigger_configured_clear_fault ("write", "before", path, ""); @@ -732,313 +788,320 @@ int LazyFS::lfs_write (const char* path, // std::printf ("\t[write] direct_io=1, flushing data..."); - res = pwrite (fd, buf, size, offset); + if (fi == NULL) + close (fd); - } else { + return pwrite (fd, buf, size, offset); + } - // ---------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------- - bool locked_this = this_ ()->FSCache->lockItemCheckExists (inode); + bool locked_this = this_ ()->FSCache->lockItemCheckExists (inode); - bool cache_had_owner = this_ ()->FSCache->has_content_cached (inode); - off_t FILE_SIZE_BEFORE = 0; + bool cache_had_owner = this_ ()->FSCache->has_content_cached (inode); + off_t FILE_SIZE_BEFORE = 0; - if (!locked_this) { + if (!locked_this) { - FILE_SIZE_BEFORE = stats.st_size; + FILE_SIZE_BEFORE = stats.st_size; - } else { + } else { - Metadata* meta_now = this_ ()->FSCache->get_content_metadata (inode); + Metadata* meta_now = this_ ()->FSCache->get_content_metadata (inode); - if (meta_now != nullptr) - FILE_SIZE_BEFORE = this_ ()->FSCache->get_content_metadata (inode)->size; + if (meta_now != nullptr) + FILE_SIZE_BEFORE = this_ ()->FSCache->get_content_metadata (inode)->size; - this_ ()->FSCache->unlockItem (inode); - } + this_ ()->FSCache->unlockItem (inode); + } - // std::printf ("\twrite: file size before is %d bytes\n", (int)FILE_SIZE_BEFORE); + // std::printf ("\twrite: file size before is %d bytes\n", (int)FILE_SIZE_BEFORE); - // ---------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------- - if (fi != NULL) { + if (fi != NULL) { - if (FILE_SIZE_BEFORE < offset) { + if (FILE_SIZE_BEFORE < offset) { - // fill sparse write with zeros, how? - // [file_size_offset, offset - 1] = zeros + // fill sparse write with zeros, how? + // [file_size_offset, offset - 1] = zeros - spdlog::info ("[lazyfs.ops]: Calling a sparse write."); + spdlog::info ("[lazyfs.ops]: Calling a sparse write."); - off_t size_to_fill = offset - std::max (FILE_SIZE_BEFORE, (off_t)0); + off_t size_to_fill = offset - std::max (FILE_SIZE_BEFORE, (off_t)0); - if (size_to_fill > 0) { + if (size_to_fill > 0) { - char* fill_zeros = (char*)calloc (size_to_fill, 1); - lfs_write (path, fill_zeros, size_to_fill, FILE_SIZE_BEFORE, NULL); - free (fill_zeros); - } + char* fill_zeros = (char*)calloc (size_to_fill, 1); + lfs_write (path, fill_zeros, size_to_fill, FILE_SIZE_BEFORE, NULL); + free (fill_zeros); } } + } - // ---------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------- - off_t blk_low = offset / IO_BLOCK_SIZE; - off_t blk_high = (offset + size - 1) / IO_BLOCK_SIZE; - off_t blk_readable_from = 0; - off_t blk_readable_to = 0; - off_t data_allocated = 0; - off_t data_buffer_iterator = 0; - int fd_caching = open (path, O_RDONLY); + off_t blk_low = offset / IO_BLOCK_SIZE; + off_t blk_high = (offset + size - 1) / IO_BLOCK_SIZE; + off_t blk_readable_from = 0; + off_t blk_readable_to = 0; + off_t data_allocated = 0; + off_t data_buffer_iterator = 0; + int fd_caching = open (path, O_RDONLY); - char block_caching_buffer[IO_BLOCK_SIZE]; - map> put_mapping; + char block_caching_buffer[IO_BLOCK_SIZE]; + map> put_mapping; - bool cache_full = (this_ ()->FSCache->get_cache_usage () == 100) && - !this_ ()->FSConfig->APPLY_LRU_EVICTION; + bool cache_full = + (this_ ()->FSCache->get_cache_usage () == 100) && !this_ ()->FSConfig->APPLY_LRU_EVICTION; - // ---------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------- - // std::printf ("\t[write] from_block=%d to_block=%d\n", blk_low, blk_high); + // std::printf ("\t[write] from_block=%d to_block=%d\n", blk_low, blk_high); - for (off_t CURR_BLK_IDX = blk_low; CURR_BLK_IDX <= blk_high; CURR_BLK_IDX++) { + for (off_t CURR_BLK_IDX = blk_low; CURR_BLK_IDX <= blk_high; CURR_BLK_IDX++) { - /* - > Calculate readable block offsets: + /* + > Calculate readable block offsets: - For each block, depending on the 'offset' and 'size' provided, - the write is bounded from an index to another in each block. - Each pair of offsets varies from [0 <-> IO_BLOCK_SIZE]. - */ + For each block, depending on the 'offset' and 'size' provided, + the write is bounded from an index to another in each block. + Each pair of offsets varies from [0 <-> IO_BLOCK_SIZE]. + */ - blk_readable_from = (CURR_BLK_IDX == blk_low) ? (offset % IO_BLOCK_SIZE) : 0; + blk_readable_from = (CURR_BLK_IDX == blk_low) ? (offset % IO_BLOCK_SIZE) : 0; - if (CURR_BLK_IDX == blk_high) - blk_readable_to = ((offset + size - 1) % IO_BLOCK_SIZE); - else if ((CURR_BLK_IDX == blk_low) && ((offset + size - 1) < IO_BLOCK_SIZE)) - blk_readable_to = offset + size - 1; - else if (CURR_BLK_IDX < blk_high) - blk_readable_to = IO_BLOCK_SIZE - 1; - else if (CURR_BLK_IDX == blk_high) - blk_readable_to = size - data_allocated - 1; + if (CURR_BLK_IDX == blk_high) + blk_readable_to = ((offset + size - 1) % IO_BLOCK_SIZE); + else if ((CURR_BLK_IDX == blk_low) && ((offset + size - 1) < IO_BLOCK_SIZE)) + blk_readable_to = offset + size - 1; + else if (CURR_BLK_IDX < blk_high) + blk_readable_to = IO_BLOCK_SIZE - 1; + else if (CURR_BLK_IDX == blk_high) + blk_readable_to = size - data_allocated - 1; - // data_allocated += blk_readable_to - blk_readable_from + 1; + // data_allocated += blk_readable_to - blk_readable_from + 1; - bool is_block_cached = this_ ()->FSCache->is_block_cached (inode, CURR_BLK_IDX); + bool is_block_cached = this_ ()->FSCache->is_block_cached (inode, CURR_BLK_IDX); - if (is_block_cached == false) { + if (is_block_cached == false) { - bool needs_pread = FILE_SIZE_BEFORE > CURR_BLK_IDX * IO_BLOCK_SIZE; + bool needs_pread = FILE_SIZE_BEFORE > CURR_BLK_IDX * IO_BLOCK_SIZE; - /* - > Block not found in the caching lib: + /* + > Block not found in the caching lib: - Try to cache it using pread first then inserting into the cache, - if any of these fails, pwrite it to the underlying FS. - */ + Try to cache it using pread first then inserting into the cache, + if any of these fails, pwrite it to the underlying FS. + */ - if (fd_caching >= 0) { + if (fd_caching >= 0) { - // Always block sized reads for pread calls + // Always block sized reads for pread calls - int pread_res = 0; + int pread_res = 0; - if (cache_full) - needs_pread = false; + if (cache_full) + needs_pread = false; - if (needs_pread) { + if (needs_pread) { - pread_res = pread (fd_caching, - block_caching_buffer, - IO_BLOCK_SIZE, - CURR_BLK_IDX * IO_BLOCK_SIZE); - } + pread_res = pread (fd_caching, + block_caching_buffer, + IO_BLOCK_SIZE, + CURR_BLK_IDX * IO_BLOCK_SIZE); + } - if (pread_res < 0) { + if (pread_res < 0) { - // Read failed for this file, - // We assume that the file is not reachable + // Read failed for this file, + // We assume that the file is not reachable - res = -1; - break; + res = -1; + break; - } else { + } else { - const char* cache_buf; - size_t cache_wr_sz; - off_t cache_from; - off_t cache_to; + const char* cache_buf; + size_t cache_wr_sz; + off_t cache_from; + off_t cache_to; - if ((not needs_pread) || (pread_res == 0)) { + if ((not needs_pread) || (pread_res == 0)) { - cache_buf = buf + data_buffer_iterator; - cache_wr_sz = blk_readable_to - blk_readable_from + 1; - cache_from = blk_readable_from; - cache_to = blk_readable_to; + cache_buf = buf + data_buffer_iterator; + cache_wr_sz = blk_readable_to - blk_readable_from + 1; + cache_from = blk_readable_from; + cache_to = blk_readable_to; - } else { + } else { - memcpy (block_caching_buffer + blk_readable_from, - buf + data_buffer_iterator, - blk_readable_to - blk_readable_from + 1); + memcpy (block_caching_buffer + blk_readable_from, + buf + data_buffer_iterator, + blk_readable_to - blk_readable_from + 1); - if (blk_readable_from - pread_res > 0) - memset (block_caching_buffer + pread_res, - 0, - blk_readable_from - pread_res); + if (blk_readable_from - pread_res > 0) + memset (block_caching_buffer + pread_res, + 0, + blk_readable_from - pread_res); - cache_buf = block_caching_buffer; + cache_buf = block_caching_buffer; - cache_wr_sz = - pread_res > (blk_readable_to + 1) ? pread_res : blk_readable_to + 1; + cache_wr_sz = + pread_res > (blk_readable_to + 1) ? pread_res : blk_readable_to + 1; - cache_from = 0; - cache_to = cache_wr_sz - 1; - } + cache_from = 0; + cache_to = cache_wr_sz - 1; + } - // Increase the ammount of bytes already written from the argument - // 'size' - data_allocated += blk_readable_to - blk_readable_from + 1; + // Increase the ammount of bytes already written from the argument + // 'size' + data_allocated += blk_readable_to - blk_readable_from + 1; - bool curr_block_put_exists = false; - std::map put_res; + bool curr_block_put_exists = false; + std::map put_res; - if (!cache_full) { + if (!cache_full) { - put_res = this_ ()->FSCache->put_data_blocks ( - inode, - {{CURR_BLK_IDX, {cache_buf, cache_wr_sz, cache_from, cache_to}}}, - OP_WRITE); - } + put_res = this_ ()->FSCache->put_data_blocks ( + inode, + {{CURR_BLK_IDX, {cache_buf, cache_wr_sz, cache_from, cache_to}}}, + OP_WRITE); + } - curr_block_put_exists = put_res.find (CURR_BLK_IDX) != put_res.end (); + curr_block_put_exists = put_res.find (CURR_BLK_IDX) != put_res.end (); - if (cache_full || - (!curr_block_put_exists || (put_res.at (CURR_BLK_IDX) == false))) { + if (cache_full || + (!curr_block_put_exists || (put_res.at (CURR_BLK_IDX) == false))) { - // Block allocation in cache failed + // Block allocation in cache failed - int pwrite_res = pwrite (fd, - cache_buf, - cache_wr_sz, - CURR_BLK_IDX * IO_BLOCK_SIZE + cache_from); + int pwrite_res = pwrite (fd, + cache_buf, + cache_wr_sz, + CURR_BLK_IDX * IO_BLOCK_SIZE + cache_from); - if (pwrite_res != cache_wr_sz) { - res = -1; - break; - } + if (pwrite_res != cache_wr_sz) { + res = -1; + break; } } + } - } else { + } else { - // Read failed for this file, - // We assume that the file is not reachable + // Read failed for this file, + // We assume that the file is not reachable - res = -1; - break; - } + res = -1; + break; + } - } else { + } else { - /* - > Block seems to be cached: + /* + > Block seems to be cached: - Try to update block data by replacing block contents for that offsets. - If it fails, sync data... - */ + Try to update block data by replacing block contents for that offsets. + If it fails, sync data... + */ - // Increase the ammount of bytes already written from the argument 'size' - data_allocated += blk_readable_to - blk_readable_from + 1; + // Increase the ammount of bytes already written from the argument 'size' + data_allocated += blk_readable_to - blk_readable_from + 1; - auto put_res = - this_ ()->FSCache->put_data_blocks (inode, - {{CURR_BLK_IDX, - {buf + data_buffer_iterator, - blk_readable_to - blk_readable_from + 1, - blk_readable_from, - blk_readable_to}}}, - OP_WRITE); - bool curr_block_put_exists = put_res.find (CURR_BLK_IDX) != put_res.end (); - - if (!curr_block_put_exists || put_res.at (CURR_BLK_IDX) == false) { - - int pwrite_res = pwrite (fd, - buf + data_buffer_iterator, - blk_readable_to - blk_readable_from + 1, - CURR_BLK_IDX * IO_BLOCK_SIZE + blk_readable_from); - - if (pwrite_res != (blk_readable_to - blk_readable_from + 1)) { - res = -1; - break; - } + auto put_res = + this_ ()->FSCache->put_data_blocks (inode, + {{CURR_BLK_IDX, + {buf + data_buffer_iterator, + blk_readable_to - blk_readable_from + 1, + blk_readable_from, + blk_readable_to}}}, + OP_WRITE); + bool curr_block_put_exists = put_res.find (CURR_BLK_IDX) != put_res.end (); + + if (!curr_block_put_exists || put_res.at (CURR_BLK_IDX) == false) { + + int pwrite_res = pwrite (fd, + buf + data_buffer_iterator, + blk_readable_to - blk_readable_from + 1, + CURR_BLK_IDX * IO_BLOCK_SIZE + blk_readable_from); + + if (pwrite_res != (blk_readable_to - blk_readable_from + 1)) { + res = -1; + break; } } - - data_buffer_iterator = data_allocated; } - // ---------------------------------------------------------------------------------- + data_buffer_iterator = data_allocated; + } - // close (fd_caching); + // ---------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------- + // close (fd_caching); - bool locked = this_ ()->FSCache->lockItemCheckExists (inode); + // ---------------------------------------------------------------------------------- - if (locked) { + bool locked = this_ ()->FSCache->lockItemCheckExists (inode); - off_t was_written_until_offset = offset + size; + if (locked) { - Metadata meta; - meta.size = was_written_until_offset > FILE_SIZE_BEFORE ? was_written_until_offset - : FILE_SIZE_BEFORE; + off_t was_written_until_offset = offset + size; - vector values_to_change; - values_to_change.push_back ("size"); + Metadata meta; + meta.size = was_written_until_offset > FILE_SIZE_BEFORE ? was_written_until_offset + : FILE_SIZE_BEFORE; - struct timespec modify_time; - clock_gettime (CLOCK_REALTIME, &modify_time); - meta.mtim = modify_time; - values_to_change.push_back ("mtime"); + vector values_to_change; + values_to_change.push_back ("size"); - if (meta.size > FILE_SIZE_BEFORE) { + struct timespec modify_time; + clock_gettime (CLOCK_REALTIME, &modify_time); + meta.mtim = modify_time; + values_to_change.push_back ("mtime"); - meta.ctim = modify_time; - values_to_change.push_back ("ctime"); - } + if (meta.size > FILE_SIZE_BEFORE) { - this_ ()->FSCache->update_content_metadata (inode, meta, values_to_change); + meta.ctim = modify_time; + values_to_change.push_back ("ctime"); + } - // std::printf ("\twrite: file size now is %d bytes\n", (int)meta.size); + this_ ()->FSCache->update_content_metadata (inode, meta, values_to_change); - this_ ()->FSCache->unlockItem (inode); - } + // std::printf ("\twrite: file size now is %d bytes\n", (int)meta.size); - close (fd_caching); + this_ ()->FSCache->unlockItem (inode); } + close (fd_caching); + // ---------------------------------------------------------------------------------- - - bool crash_added = this_ () -> persist_write(path,buf,size,offset) || this_ () -> split_write(path,buf,size,offset); //only one will be injected, becaus eby now we only allow one - // res should be = actual bytes written as pwrite could fail... - res = size; + bool crash_added = this_ ()->persist_write (path, buf, size, offset) || + this_ ()->split_write ( + path, + buf, + size, + offset); // only one will be injected, becaus eby now we only allow one // std::printf ("\twrite: returning %d bytes\n", res); + if (crash_added && this_ ()->kill_before.load ()) + spdlog::warn ("Syscall write returned. LazyFS will crash before the next system call."); + else { + this_ ()->trigger_crash_fault ("write", "after", path, "", false); + this_ ()->trigger_configured_clear_fault ("write", "after", path, "", false); + } + + // res should be = actual bytes written as pwrite could fail... + res = size; + if (res == -1) res = -errno; if (fi == NULL) close (fd); - if (crash_added && this_ ()->kill_before.load()) spdlog::critical("Syscall write returned. LazyFS will crash before the next system call."); - else { - this_ ()->trigger_crash_fault ("write", "after", path, "", false); - this_ ()->trigger_configured_clear_fault ("write", "after", path, "", false); - } - return res; } @@ -1048,7 +1111,7 @@ int LazyFS::lfs_read (const char* path, off_t offset, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("read", "before", path, ""); this_ ()->trigger_configured_clear_fault ("read", "before", path, ""); @@ -1290,7 +1353,7 @@ int LazyFS::lfs_read (const char* path, int LazyFS::lfs_fsync (const char* path, int isdatasync, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("fsync", "before", path, ""); this_ ()->trigger_configured_clear_fault ("fsync", "before", path, ""); @@ -1303,9 +1366,9 @@ int LazyFS::lfs_fsync (const char* path, int isdatasync, struct fuse_file_info* if (this_ ()->FSConfig->log_all_operations) { spdlog::info ("[lazyfs.ops]: {}(path={},isdatasync={})", __FUNCTION__, path, isdatasync); } - - this_ ()->restart_counter(path,"write"); //Reset counter of op write for this path - this_ ()->check_and_delete_pendingwrite(path); //If there's a pending write, remove it + + this_ ()->restart_counter (path, "write"); // Reset counter of op write for this path + this_ ()->check_and_delete_pendingwrite (path); // If there's a pending write, remove it string owner (path); string inode = this_ ()->FSCache->get_original_inode (owner); @@ -1323,13 +1386,13 @@ int LazyFS::lfs_fsync (const char* path, int isdatasync, struct fuse_file_info* this_ ()->trigger_crash_fault ("fsync", "after", path, "", false); this_ ()->trigger_configured_clear_fault ("fsync", "after", path, "", false); - + return res; } int LazyFS::lfs_is_dir_empty (const char* dirname) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); struct dirent* from_DIRENT; DIR* from_DIR = opendir (dirname); @@ -1421,7 +1484,7 @@ int LazyFS::lfs_recursive_rename (const char* from, const char* to, unsigned int int LazyFS::lfs_rename (const char* from, const char* to, unsigned int flags) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("rename", "before", from, to); this_ ()->trigger_configured_clear_fault ("rename", "before", from, to); @@ -1468,7 +1531,7 @@ int LazyFS::lfs_rename (const char* from, const char* to, unsigned int flags) { int LazyFS::lfs_truncate (const char* path, off_t truncate_size, struct fuse_file_info* fi) { cout << ">> FTRUNCATE" << endl; - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("truncate", "before", path, ""); this_ ()->trigger_configured_clear_fault ("truncate", "before", path, ""); @@ -1615,7 +1678,7 @@ int LazyFS::lfs_truncate (const char* path, off_t truncate_size, struct fuse_fil int LazyFS::lfs_symlink (const char* from, const char* to) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("symlink", "before", from, to); this_ ()->trigger_configured_clear_fault ("symlink", "before", from, to); @@ -1639,7 +1702,7 @@ int LazyFS::lfs_symlink (const char* from, const char* to) { int LazyFS::lfs_access (const char* path, int mask) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("access", "before", path, ""); this_ ()->trigger_configured_clear_fault ("access", "before", path, ""); @@ -1664,7 +1727,7 @@ int LazyFS::lfs_access (const char* path, int mask) { int LazyFS::lfs_mkdir (const char* path, mode_t mode) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1683,7 +1746,7 @@ int LazyFS::lfs_mkdir (const char* path, mode_t mode) { int LazyFS::lfs_link (const char* from, const char* to) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("link", "before", from, to); this_ ()->trigger_configured_clear_fault ("link", "before", from, to); @@ -1713,7 +1776,7 @@ int LazyFS::lfs_link (const char* from, const char* to) { int LazyFS::lfs_readlink (const char* path, char* buf, size_t size) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1733,7 +1796,7 @@ int LazyFS::lfs_readlink (const char* path, char* buf, size_t size) { int LazyFS::lfs_release (const char* path, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1750,7 +1813,7 @@ int LazyFS::lfs_release (const char* path, struct fuse_file_info* fi) { int LazyFS::lfs_rmdir (const char* path) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1769,7 +1832,7 @@ int LazyFS::lfs_rmdir (const char* path) { int LazyFS::lfs_chmod (const char* path, mode_t mode, struct fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1789,7 +1852,7 @@ int LazyFS::lfs_chmod (const char* path, mode_t mode, struct fuse_file_info* fi) int LazyFS::lfs_chown (const char* path, uid_t uid, gid_t gid, fuse_file_info* fi) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); std::shared_lock lock (cache_command_lock); @@ -1908,7 +1971,7 @@ off_t LazyFS::lfs_lseek (const char* path, off_t off, int whence, struct fuse_fi int LazyFS::lfs_unlink (const char* path) { - this_ ()->check_kill_before(); + this_ ()->check_kill_before (); this_ ()->trigger_crash_fault ("unlink", "before", path, ""); this_ ()->trigger_configured_clear_fault ("unlink", "before", path, ""); @@ -1941,25 +2004,27 @@ int LazyFS::lfs_unlink (const char* path) { } void LazyFS::print_faults () { - for (const auto& fault_pair : *(this_()->faults)) { + for (const auto& fault_pair : *(this_ ()->faults)) { cout << "\n>> Faults for path: " << fault_pair.first << endl; for (const auto& fault : fault_pair.second) { - fault->pretty_print(); + fault->pretty_print (); } } cout << "\n>> Crash Faults Before Map:" << endl; - for (const auto& pair : this_()->crash_faults_before_map) { + for (const auto& pair : this_ ()->crash_faults_before_map) { cout << "Operation: " << pair.first << endl; for (const auto& fault : pair.second) { - cout << " From Regex: " << fault.first.mark_count() << ", To Regex: " << fault.second << endl; + cout << " From Regex: " << fault.first.mark_count () << ", To Regex: " << fault.second + << endl; } } cout << "\n>> Crash Faults After Map:" << endl; - for (const auto& pair : this_()->crash_faults_after_map) { + for (const auto& pair : this_ ()->crash_faults_after_map) { cout << "Operation: " << pair.first << endl; for (const auto& fault : pair.second) { - cout << " From Regex: " << fault.first.mark_count() << ", To Regex: " << fault.second << endl; + cout << " From Regex: " << fault.first.mark_count () << ", To Regex: " << fault.second + << endl; } } } diff --git a/libs/libpcache/include/cache/cache.hpp b/libs/libpcache/include/cache/cache.hpp index 54d9257..8fdfa91 100644 --- a/libs/libpcache/include/cache/cache.hpp +++ b/libs/libpcache/include/cache/cache.hpp @@ -56,7 +56,7 @@ class Cache { */ cache::config::Config* cache_config; /** - * @brief Maps content ids (e.g. file names) to the contents + * @brief Maps content ids (e.g. inodes) to the contents * */ unordered_map contents; @@ -240,9 +240,9 @@ class Cache { * @param owner the content id * @param only_sync_data only sync data from content * @param orig_path original path to write data - * @return int true if item was removed + * @return bool true if data was synced */ - int sync_owner (string owner, bool only_sync_data, char* orig_path); + bool sync_owner (string owner, bool only_sync_data, char* orig_path); /** * @brief Renames an item id @@ -282,10 +282,10 @@ class Cache { * @param owner the content id * @param path original path name * @param parts parts from file that will be removed - * @return int true if item was removed + * @return bool true if parts were synced * */ - int partial_file_sync (string owner, char* path, string parts); + bool partial_file_sync (string owner, char* path, string parts); /** * @brief Gets the list of files that have unsynced data, mapped to @@ -320,6 +320,14 @@ class Cache { * @return vector files mapped to that inode */ vector find_files_mapped_to_inode (string inode); + + /** + * @brief Retrieves a list of unsynced inodes. + * + * @return std::vector A vector of unsynced inodes. + */ + vector unsynced_inodes(); + }; } // namespace cache diff --git a/libs/libpcache/include/faults/faults.hpp b/libs/libpcache/include/faults/faults.hpp index 891edf5..752714d 100644 --- a/libs/libpcache/include/faults/faults.hpp +++ b/libs/libpcache/include/faults/faults.hpp @@ -341,6 +341,11 @@ class SyncPageF : public Fault { */ bool ret; + /** + * @brief True if we want to fsync other files. + */ + bool sync_other_files; + /** * @brief Constructor for Fault. * @@ -352,8 +357,9 @@ class SyncPageF : public Fault { * @param crash If the fault is a crash fault. * @param pages Pages to clear. * @param ret If the current system call is finished before crashing. + * @param sync_other_files If we want to fsync other files. */ - SyncPageF(string timing, string op, string from, string to, int occurrence, string pages, bool ret); + SyncPageF(string timing, string op, string from, string to, int occurrence, string pages, bool ret, bool fsync_other_files = true); ~SyncPageF (); diff --git a/libs/libpcache/src/cache.cpp b/libs/libpcache/src/cache.cpp index f46475a..ed9dd9b 100644 --- a/libs/libpcache/src/cache.cpp +++ b/libs/libpcache/src/cache.cpp @@ -352,7 +352,7 @@ bool Cache::truncate_item (string owner, off_t new_size) { return true; } -int Cache::sync_owner (string owner, bool only_sync_data, char* orig_path) { +bool Cache::sync_owner (string owner, bool only_sync_data, char* orig_path) { std::unique_lock lock (lock_cache_mtx, std::defer_lock); lock.lock (); @@ -373,7 +373,10 @@ int Cache::sync_owner (string owner, bool only_sync_data, char* orig_path) { off_t last_size = get_content_metadata (owner)->size; res = this->engine->sync_pages (owner, last_size, orig_path); - _get_content_ptr (owner)->set_data_sync_flag (true); + if (res) + _get_content_ptr (owner)->set_data_sync_flag (true); + else + spdlog::warn ("[cache] sync_pages failed"); if (not only_sync_data) { @@ -560,18 +563,17 @@ void Cache::full_checkpoint () { this->sync_owner (it.second, false, (char*)it.first.c_str ()); } -int Cache::partial_file_sync (string owner, char* path, string parts) { +bool Cache::partial_file_sync (string owner, char* path, string parts) { string inode = get_original_inode (owner); off_t last_size = get_content_metadata (inode)->size; //spdlog::info ("[CACHE]: partial file sync for inode: {} path: {} parts: {}", inode, path, parts); - int res = this->engine->partial_sync_pages (inode, last_size, path, parts); + bool res = this->engine->partial_sync_pages (inode, last_size, path, parts); if (this->engine->is_owner_synced (inode)) { _get_content_ptr (inode)->set_data_sync_flag (true); - cout << "SYNCED" << endl; } return res; @@ -608,4 +610,19 @@ vector Cache::find_files_mapped_to_inode (string inode) { return res; } +vector Cache::unsynced_inodes() { + + std::lock_guard lock (lock_cache_mtx); + + vector res; + + for (auto const& it : this->contents) { + if (not it.second->is_synced ()) { + res.push_back (it.first); + } + } + + return res; +} + } // namespace cache \ No newline at end of file diff --git a/libs/libpcache/src/engine/backends/custom/custom_cache.cpp b/libs/libpcache/src/engine/backends/custom/custom_cache.cpp index 9489f63..05b28ed 100644 --- a/libs/libpcache/src/engine/backends/custom/custom_cache.cpp +++ b/libs/libpcache/src/engine/backends/custom/custom_cache.cpp @@ -474,6 +474,7 @@ void CustomCacheEngine::make_block_readable_to_offset (string cid, bool CustomCacheEngine::sync_pages (string owner, off_t size, char* orig_path) { std::unique_lock lock (lock_cache_mtx); + bool res = true; int fd = open (orig_path, O_WRONLY); @@ -545,6 +546,11 @@ bool CustomCacheEngine::sync_pages (string owner, off_t size, char* orig_path) { } wrote_bytes += pwritev (fd, iov, page_streak, page_streak_last_offset); + + if (wrote_bytes < 0) { + spdlog::warn ("[cache] pwritev of partial sync failed"); + res = false; + } page_streak = 0; @@ -556,18 +562,19 @@ bool CustomCacheEngine::sync_pages (string owner, off_t size, char* orig_path) { } if (ftruncate (fd, size) < 0) { - spdlog::info ("ftruncate: failed"); + spdlog::warn ("ftruncate: failed"); } close (fd); - return 0; + return res; } bool CustomCacheEngine::partial_sync_pages (string owner, off_t last_size, char* orig_path, string parts) { std::unique_lock lock (lock_cache_mtx); + bool res = true; int fd = open (orig_path, O_WRONLY); if (this->owner_pages_mapping.find (owner) != this->owner_pages_mapping.end ()) { @@ -680,6 +687,11 @@ bool CustomCacheEngine::partial_sync_pages (string owner, off_t last_size, char* wrote_bytes += pwritev (fd, iov, page_streak, page_streak_last_offset); + if (wrote_bytes < 0) { + spdlog::warn ("[cache] pwritev of partial sync failed"); + res = false; + } + page_streak = 0; page_chunk.clear (); @@ -690,12 +702,12 @@ bool CustomCacheEngine::partial_sync_pages (string owner, off_t last_size, char* } if (ftruncate (fd, last_size) < 0) { - spdlog::info ("ftruncate: failed"); + spdlog::warn ("[cache] ftruncate of partial sync failed"); } close (fd); - return 0; + return res; } bool CustomCacheEngine::is_owner_synced (string owner) { @@ -827,4 +839,4 @@ vector, int>> CustomCacheEngine::get_dirty_blocks_info return res; } -} // namespace cache::engine::backends::custom +} // namespace cache::engine::backends::custom \ No newline at end of file diff --git a/libs/libpcache/src/faults.cpp b/libs/libpcache/src/faults.cpp index e05e65f..291c0cc 100644 --- a/libs/libpcache/src/faults.cpp +++ b/libs/libpcache/src/faults.cpp @@ -222,7 +222,7 @@ void ClearF::pretty_print() const { // Clear page Fault -SyncPageF::SyncPageF (string timing, string op, string from, string to, int occurrence, string pages, bool ret) : Fault(CLEAR) { +SyncPageF::SyncPageF (string timing, string op, string from, string to, int occurrence, string pages, bool ret, bool sync_other_files) : Fault(CLEAR) { this->timing = timing; this->op = op; this->from = from; @@ -231,6 +231,7 @@ SyncPageF::SyncPageF (string timing, string op, string from, string to, int occu this->pages = pages; (this->counter).store(0); this->ret = ret; + this->sync_other_files = sync_other_files; } SyncPageF::~SyncPageF(){} @@ -275,6 +276,7 @@ void SyncPageF::pretty_print() const { cout << " Occurrence: " << this->occurrence << endl; cout << " Pages: " << this->pages << endl; cout << " Return: " << (this->ret ? "true" : "false") << endl; + cout << " Sync other files: " << (this->sync_other_files ? "true" : "false") << endl; } // namespace faults