From 99512dacbb53f8e053779d65b5c604c5ab45b745 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 22 Jul 2021 20:24:40 -0400 Subject: [PATCH 01/18] pickle test script/small code change --- src/load.cpp | 2 +- src/pkl.cpp | 5 +- tests/compile.sh | 7 +++ tests/pkl_load_test.py | 140 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 tests/compile.sh create mode 100755 tests/pkl_load_test.py diff --git a/src/load.cpp b/src/load.cpp index 95475e4..1ca9946 100644 --- a/src/load.cpp +++ b/src/load.cpp @@ -19,7 +19,7 @@ int main(int argc, char **argv) } // write the config file to pass the output file path - int cfgfd = open(VERIFS_LOAD_CFG, O_WRONLY | O_CREAT | O_TRUNC); + int cfgfd = open(VERIFS_LOAD_CFG, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (cfgfd < 0) { fprintf(stderr, "Cannot open/create %s: (%d:%s)\n", VERIFS_LOAD_CFG, errno, errnoname(errno)); diff --git a/src/pkl.cpp b/src/pkl.cpp index aadd8aa..37217d0 100644 --- a/src/pkl.cpp +++ b/src/pkl.cpp @@ -4,8 +4,7 @@ #include "common.h" #include "cr.h" -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); @@ -19,7 +18,7 @@ int main(int argc, char **argv) } // write the config file to pass the output file path - int cfgfd = open(VERIFS_PICKLE_CFG, O_WRONLY | O_CREAT | O_TRUNC); + int cfgfd = open(VERIFS_PICKLE_CFG, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (cfgfd < 0) { fprintf(stderr, "Cannot open/create %s: (%d:%s)\n", VERIFS_PICKLE_CFG, errno, errnoname(errno)); diff --git a/tests/compile.sh b/tests/compile.sh new file mode 100644 index 0000000..53dbde2 --- /dev/null +++ b/tests/compile.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +rm -rf ../build/* +cd ../build/ || exit +cmake ../src +make +sudo make install \ No newline at end of file diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py new file mode 100755 index 0000000..2aec0e2 --- /dev/null +++ b/tests/pkl_load_test.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +import glob +import subprocess +import os +import sys +import time +import errno + +# config +fs_name = 'fuse-cpp-ramfs' +path_to_fs = 'mnt/fuse-cpp-ramfs' +absfs_path = '../../fs-state/absfs' +pkl_path = '../build/pkl' +load_path = '../build/load' +# + +print(sys.platform) + +config_list = [] +size = 0 + + +def make_sure_path_exists(path): + try: + os.makedirs(path) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + + +def get_fs_signature(): + p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) + p2 = subprocess.Popen(['awk', 'END{print $NF}'], stdin=p1.stdout, stdout=subprocess.PIPE) + return p2.communicate()[0] + + +def pickle_save_signature(): + global size + config_list.append(get_fs_signature()) + subprocess.run([pkl_path, path_to_fs, 'pickle_tmp{}'.format(size)]) + size += 1 + + +def load_verify_signature(i): + global size + subprocess.run([load_path, path_to_fs, 'pickle_tmp{}'.format(i)]) + signature = config_list[i] + new_signature = get_fs_signature() + if new_signature == signature: + print('loaded pickle file at index {} passed verification, signature: {}'.format(i, signature)) + else: + raise Exception('signature at index {} has a discrepancy: {} -> {}'.format(i, signature, new_signature)) + + +def clean_files(prefix, cwd=None): + if prefix == '/' or (prefix == '' and cwd is None): + raise Exception('dangerous action') + subprocess.run(['rm', '-rf', '{}*'.format(prefix)], cwd=cwd) + + +def run(cmd, cwd=path_to_fs): + subprocess.run(cmd, cwd=cwd) + + +# =================================================== + + +def perform_test(): + for i in range(100): + run(['mkdir', 'pickle_dir_1_{}'.format(i)]) + run(['touch', 'pickle_file_1_{}'.format(i)]) + pickle_save_signature() + + time.sleep(1) + + for i in range(100, 200): + run(['mkdir', 'pickle_dir_1_{}'.format(i)]) + run(['touch', 'pickle_file_1_{}'.format(i)]) + load_verify_signature(0) + + for i in range(100): + run(['mkdir', 'pickle_dir_2_{}'.format(i)], '{}/pickle_dir_1_{}'.format(path_to_fs, i)) + for j in range(5): + run(['touch', 'pickle_file_2_{}'.format(j)], + '{}/pickle_dir_1_{}/pickle_dir_2_{}'.format(path_to_fs, i, i)) + run(['chmod','a+x', 'pickle_file_2_{}'.format(j)], + '{}/pickle_dir_1_{}/pickle_dir_2_{}'.format(path_to_fs, i, i)) + + pickle_save_signature() + + time.sleep(1) + + for i in range(100): + run(['rm', '-rf', 'pickle_dir_2_{}'.format(i)], '{}/pickle_dir_1_{}'.format(path_to_fs, i)) + + load_verify_signature(1) + + for i in range(100): + run(['mv', 'pickle_dir_1_{}'.format(i),'pickle_new_dir_1_{}'.format(i)]) + run(['mv', 'pickle_new_dir_1_0','pickle_new_dir_1_2/pickle_new_dir_1_0']) + + pickle_save_signature() + + time.sleep(1) + + run(['rm', '-rf', '*']) + + load_verify_signature(2) + + +# =================================================== + +make_sure_path_exists(path_to_fs) + +clean_files('', path_to_fs) + +child = subprocess.Popen([fs_name, + path_to_fs]) + +time.sleep(1) + +perform_test() + +# If you unmount too soon, the mountpoint won't be available. + +if sys.platform == 'darwin' or sys.platform == 'linux': + subprocess.run(['umount', + path_to_fs]) +else: + subprocess.run(['fusermount', '-u', + path_to_fs]) + +print('perform cleanup......') + +child.wait() + +for fl in glob.glob('pickle_tmp*'): + os.remove(fl) + +sys.exit(child.returncode) From fd93300c3985a6a41c163fa61a33c249cccafbcb Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Mon, 26 Jul 2021 09:33:25 -0400 Subject: [PATCH 02/18] racer support/pickle&load initial implementation --- src/ckpt.cpp | 2 +- src/pickle.cpp | 45 +++++++++++++++- tests/pkl_load_test.py | 114 +++++++++++++++++++++++------------------ 3 files changed, 108 insertions(+), 53 deletions(-) diff --git a/src/ckpt.cpp b/src/ckpt.cpp index 090cf61..af4e82b 100644 --- a/src/ckpt.cpp +++ b/src/ckpt.cpp @@ -5,7 +5,7 @@ #include "fuse_cpp_ramfs.hpp" #include "testops.h" -std::string MOUNTPOINT = VERIFS2_MOUNTPOINT; +//std::string MOUNTPOINT = VERIFS2_MOUNTPOINT; int main(int argc, char **argv) { diff --git a/src/pickle.cpp b/src/pickle.cpp index 39b5376..e2105ee 100644 --- a/src/pickle.cpp +++ b/src/pickle.cpp @@ -119,6 +119,38 @@ int pickle_file_system(int fd, std::vector& inodes, pending_delete_inodes.pop(); pending_delete_inodes.push(ino); } + + size_t num_state_pool = state_pool.size(); + write_and_hash(fd, hashctx, &num_state_pool, sizeof(num_state_pool)); + for (const auto &state: state_pool) { + uint64_t key=state.first; + write_and_hash(fd, hashctx, &key, sizeof(key)); + std::tuple + , std::queue, + struct statvfs> stored_states=state.second; + std::vector stored_files = std::get<0>(stored_states); + size_t num_stored_files = stored_files.size(); + write_and_hash(fd, hashctx, &num_stored_files, sizeof(num_stored_files)); + + for(const auto &stored_file:stored_files){ + write_and_hash(fd, hashctx, &stored_file, sizeof(stored_file)); + } + + std::queue stored_DeletedInodes = std::get<1>(stored_states); + size_t num_stored_DeletedInodes = stored_DeletedInodes.size(); + write_and_hash(fd, hashctx, &num_stored_DeletedInodes, sizeof(num_stored_DeletedInodes)); + + for (size_t i = 0; i < num_stored_DeletedInodes; ++i) { + fuse_ino_t ino = stored_DeletedInodes.front(); + write_and_hash(fd, hashctx, &ino, sizeof(ino)); + stored_DeletedInodes.pop(); + stored_DeletedInodes.push(ino); + } + + struct statvfs stored_m_stbuf = std::get<2>(stored_states); + write_and_hash(fd, hashctx, &stored_m_stbuf, sizeof(stored_m_stbuf)); + } + } catch (const pickle_error& e) { lseek(fd, fpos, SEEK_SET); return -e.get_errno(); @@ -269,7 +301,7 @@ int verify_state_file(int fd) { * @return: bytes used */ ssize_t load_file_system(const void *data, std::vector& inodes, - std::queue& pending_del_inodes, + std::queue& pending_delete_inodes, struct statvfs &fs_stat) { const char *ptr = (const char *)data; try { @@ -315,6 +347,17 @@ ssize_t load_file_system(const void *data, std::vector& inodes, } ptr += res; } + size_t num_pending_delete; + memcpy(&num_pending_delete, ptr, sizeof(num_pending_delete)); + ptr += sizeof(num_pending_delete); + for (size_t i = 0; i < num_pending_delete; ++i) { + fuse_ino_t ino; + memcpy(&ino, ptr, sizeof(ino)); + ptr += sizeof(ino); + pending_delete_inodes.push(ino); + } + + } catch (const pickle_error& e) { return -e.get_errno(); } diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py index 2aec0e2..726a3fe 100755 --- a/tests/pkl_load_test.py +++ b/tests/pkl_load_test.py @@ -5,19 +5,33 @@ import sys import time import errno +import random +import signal +from contextlib import suppress # config fs_name = 'fuse-cpp-ramfs' -path_to_fs = 'mnt/fuse-cpp-ramfs' +path_to_fs = '{}/mnt/fuse-cpp-ramfs'.format(os.getcwd()) # absolute path only absfs_path = '../../fs-state/absfs' pkl_path = '../build/pkl' load_path = '../build/load' +'''*You need to comment out (rm -rf "$DIR") in racer script for this to work correctly''' +racer_script_path = 'racer/racer.sh' +'''range format: [a,b)''' +racer_duration = (3, 6) +racer_threads = (1, 2) +num_test_attempts = (1, 2) # print(sys.platform) config_list = [] size = 0 +p = None + + +def get_random_in_range(range_tpl): + return random.randrange(range_tpl[0], range_tpl[1]) def make_sure_path_exists(path): @@ -31,18 +45,23 @@ def make_sure_path_exists(path): def get_fs_signature(): p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) p2 = subprocess.Popen(['awk', 'END{print $NF}'], stdin=p1.stdout, stdout=subprocess.PIPE) - return p2.communicate()[0] + signature = p2.communicate()[0] + if signature == b'iterating...\n': + p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) + raise Exception(p1.communicate()[0]) + return signature def pickle_save_signature(): global size - config_list.append(get_fs_signature()) + signature = get_fs_signature() + config_list.append(signature) subprocess.run([pkl_path, path_to_fs, 'pickle_tmp{}'.format(size)]) + print('saved pickle file at index {}, signature: {}'.format(size, signature)) size += 1 def load_verify_signature(i): - global size subprocess.run([load_path, path_to_fs, 'pickle_tmp{}'.format(i)]) signature = config_list[i] new_signature = get_fs_signature() @@ -62,50 +81,48 @@ def run(cmd, cwd=path_to_fs): subprocess.run(cmd, cwd=cwd) -# =================================================== - - -def perform_test(): - for i in range(100): - run(['mkdir', 'pickle_dir_1_{}'.format(i)]) - run(['touch', 'pickle_file_1_{}'.format(i)]) - pickle_save_signature() - +def clean_exit(): time.sleep(1) + # If you unmount too soon, the mountpoint won't be available. + if sys.platform == 'darwin' or sys.platform == 'linux': + subprocess.run(['umount', + path_to_fs]) + else: + subprocess.run(['fusermount', '-u', + path_to_fs]) - for i in range(100, 200): - run(['mkdir', 'pickle_dir_1_{}'.format(i)]) - run(['touch', 'pickle_file_1_{}'.format(i)]) - load_verify_signature(0) + print('perform cleanup......') - for i in range(100): - run(['mkdir', 'pickle_dir_2_{}'.format(i)], '{}/pickle_dir_1_{}'.format(path_to_fs, i)) - for j in range(5): - run(['touch', 'pickle_file_2_{}'.format(j)], - '{}/pickle_dir_1_{}/pickle_dir_2_{}'.format(path_to_fs, i, i)) - run(['chmod','a+x', 'pickle_file_2_{}'.format(j)], - '{}/pickle_dir_1_{}/pickle_dir_2_{}'.format(path_to_fs, i, i)) + for fl in glob.glob('pickle_tmp*'): + os.remove(fl) - pickle_save_signature() - time.sleep(1) +# =================================================== - for i in range(100): - run(['rm', '-rf', 'pickle_dir_2_{}'.format(i)], '{}/pickle_dir_1_{}'.format(path_to_fs, i)) - load_verify_signature(1) +def perform_test(): + global p + for i in range(get_random_in_range(num_test_attempts)): + time.sleep(3) + p = subprocess.Popen([racer_script_path, + path_to_fs, + str(get_random_in_range(racer_duration)), + str(get_random_in_range(racer_threads))]) - for i in range(100): - run(['mv', 'pickle_dir_1_{}'.format(i),'pickle_new_dir_1_{}'.format(i)]) - run(['mv', 'pickle_new_dir_1_0','pickle_new_dir_1_2/pickle_new_dir_1_0']) + p.wait() - pickle_save_signature() + pickle_save_signature() - time.sleep(1) + time.sleep(3) + + p = subprocess.Popen([racer_script_path, + path_to_fs, + str(get_random_in_range(racer_duration)), + str(get_random_in_range(racer_threads))]) - run(['rm', '-rf', '*']) + p.wait() - load_verify_signature(2) + load_verify_signature(size - 1) # =================================================== @@ -119,22 +136,17 @@ def perform_test(): time.sleep(1) -perform_test() +try: + perform_test() +except Exception as err: + print(err) + if p is not None: + pid = p.pid + with suppress(Exception): + os.kill(pid, signal.SIGINT) # or SIGINT to CTRL_C_EVENT for Windows + pass -# If you unmount too soon, the mountpoint won't be available. - -if sys.platform == 'darwin' or sys.platform == 'linux': - subprocess.run(['umount', - path_to_fs]) -else: - subprocess.run(['fusermount', '-u', - path_to_fs]) - -print('perform cleanup......') +clean_exit() child.wait() - -for fl in glob.glob('pickle_tmp*'): - os.remove(fl) - sys.exit(child.returncode) From 36bc483f71e5e7206a1eb0cb50a2d315bd86436e Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Wed, 28 Jul 2021 17:22:26 -0400 Subject: [PATCH 03/18] comment out state_pool until further solutions --- src/pickle.cpp | 4 ++-- tests/compile.sh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pickle.cpp b/src/pickle.cpp index e2105ee..f5d722a 100644 --- a/src/pickle.cpp +++ b/src/pickle.cpp @@ -120,7 +120,7 @@ int pickle_file_system(int fd, std::vector& inodes, pending_delete_inodes.push(ino); } - size_t num_state_pool = state_pool.size(); + /*size_t num_state_pool = state_pool.size(); write_and_hash(fd, hashctx, &num_state_pool, sizeof(num_state_pool)); for (const auto &state: state_pool) { uint64_t key=state.first; @@ -149,7 +149,7 @@ int pickle_file_system(int fd, std::vector& inodes, struct statvfs stored_m_stbuf = std::get<2>(stored_states); write_and_hash(fd, hashctx, &stored_m_stbuf, sizeof(stored_m_stbuf)); - } + }*/ } catch (const pickle_error& e) { lseek(fd, fpos, SEEK_SET); diff --git a/tests/compile.sh b/tests/compile.sh index 53dbde2..6157cfe 100644 --- a/tests/compile.sh +++ b/tests/compile.sh @@ -1,5 +1,6 @@ #!/bin/bash +xargs rm < ../build/install_manifest.txt rm -rf ../build/* cd ../build/ || exit cmake ../src From 52c52076aa8bb842728ed3faaabfe6c8e96d95ac Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Fri, 30 Jul 2021 20:43:43 -0400 Subject: [PATCH 04/18] modernize some cpp code for easier viewability --- src/cr_util.cpp | 4 +- src/cr_util.hpp | 2 +- src/directory.cpp | 20 ++--- src/fuse_cpp_ramfs.cpp | 166 ++++++++++++++++++++--------------------- src/fuse_cpp_ramfs.hpp | 2 +- src/inode.cpp | 16 ++-- src/main.cpp | 10 +-- 7 files changed, 109 insertions(+), 111 deletions(-) diff --git a/src/cr_util.cpp b/src/cr_util.cpp index c608e9a..8c78ca6 100644 --- a/src/cr_util.cpp +++ b/src/cr_util.cpp @@ -14,8 +14,8 @@ void print_ino_queue(std::queue DeletedInodes); std::unordered_map state_pool; int insert_state(uint64_t key, - std::tuple, std::queue, - struct statvfs> fs_states_vec) + const std::tuple, std::queue, + struct statvfs>& fs_states_vec) { auto it = state_pool.find(key); if (it != state_pool.end()) { diff --git a/src/cr_util.hpp b/src/cr_util.hpp index c6b6672..d2d3596 100644 --- a/src/cr_util.hpp +++ b/src/cr_util.hpp @@ -9,7 +9,7 @@ typedef std::tuple, std::queue, struct statvfs> verifs2_state; -int insert_state(uint64_t key, verifs2_state fs_states_vec); +int insert_state(uint64_t key, const verifs2_state& fs_states_vec); verifs2_state find_state(uint64_t key); int remove_state(uint64_t key); diff --git a/src/directory.cpp b/src/directory.cpp index e20075f..52beec8 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -171,18 +171,18 @@ Directory::ReadDirCtx* Directory::PrepareReaddir(off_t cookie) { while (readdirStates.find(cookie) != readdirStates.end()) { cookie = rand(); } - ReadDirCtx *newctx = new ReadDirCtx(cookie, copiedChildren); + auto *newctx = new ReadDirCtx(cookie, copiedChildren); readdirStates.insert({cookie, newctx}); return newctx; } bool Directory::IsEmpty() { std::shared_lock lk(childrenRwSem); - for (auto it = m_children.begin(); it != m_children.end(); ++it) { - if (it->first == "." || it->first == "..") { + for (auto & it : m_children) { + if (it.first == "." || it.first == "..") { continue; } - Inode *entry = FuseRamFs::GetInode(it->second); + Inode *entry = FuseRamFs::GetInode(it.second); /* Not empty if it has at least one undeleted inode */ if (entry && !entry->HasNoLinks()) { return false; @@ -196,13 +196,13 @@ size_t Directory::GetPickledSize() { // the number of children res += sizeof(size_t); // iterate children - for (auto it = m_children.begin(); it != m_children.end(); ++it) { + for (auto & it : m_children) { // inode number res += sizeof(fuse_ino_t); // name length field res += sizeof(size_t); // size of file name - res += it->first.size(); + res += it.first.size(); } return res; } @@ -221,17 +221,17 @@ size_t Directory::Pickle(void* &buf) { memcpy(ptr, &nchildren, sizeof(nchildren)); ptr += sizeof(nchildren); // iterate children and store - for (auto it = m_children.begin(); it != m_children.end(); ++it) { + for (auto & it : m_children) { // store inode number - fuse_ino_t ino = it->second; + fuse_ino_t ino = it.second; memcpy(ptr, &ino, sizeof(ino)); ptr += sizeof(ino); // store the length of the file name - size_t namelen = it->first.size(); + size_t namelen = it.first.size(); memcpy(ptr, &namelen, sizeof(namelen)); ptr += sizeof(namelen); // store the name string - memcpy(ptr, it->first.c_str(), namelen); + memcpy(ptr, it.first.c_str(), namelen); ptr += namelen; } return ptr - (char *)buf; diff --git a/src/fuse_cpp_ramfs.cpp b/src/fuse_cpp_ramfs.cpp index 29740e0..6a07c32 100644 --- a/src/fuse_cpp_ramfs.cpp +++ b/src/fuse_cpp_ramfs.cpp @@ -107,10 +107,8 @@ FuseRamFs::~FuseRamFs() static void free_inodes(std::vector &table) { - for (size_t i = 0; i < table.size(); ++i) { - if (table[i]) { - delete table[i]; - } + for (auto & i : table) { + delete i; } table.clear(); } @@ -130,17 +128,17 @@ int FuseRamFs::checkpoint(uint64_t key) SpecialInode *special_inode_old; SymLink *symlink_inode_old; - for (unsigned i = 0; i < Inodes.size(); i++) + for (auto & i : Inodes) { - if (Inodes[i] == nullptr){ + if (i == nullptr){ copied_files.push_back(nullptr); continue; } - inode_mode = Inodes[i]->GetMode(); + inode_mode = i->GetMode(); if (S_ISREG(inode_mode)){ - file_inode_old = dynamic_cast(Inodes[i]); - if (file_inode_old == NULL){ + file_inode_old = dynamic_cast(i); + if (file_inode_old == nullptr){ ret = -EBADF; goto err; } @@ -149,33 +147,33 @@ int FuseRamFs::checkpoint(uint64_t key) copied_files.push_back((Inode*) file_inode_copy); } else if (S_ISDIR(inode_mode)) { - dir_inode_old = dynamic_cast(Inodes[i]); - if (dir_inode_old == NULL){ + dir_inode_old = dynamic_cast(i); + if (dir_inode_old == nullptr){ ret = -EBADF; goto err; } - Directory *dir_copy = new Directory(*dir_inode_old); + auto *dir_copy = new Directory(*dir_inode_old); copied_files.push_back((Inode*) dir_copy); } else if (S_ISLNK(inode_mode)) { - symlink_inode_old = dynamic_cast(Inodes[i]); - if (symlink_inode_old == NULL){ + symlink_inode_old = dynamic_cast(i); + if (symlink_inode_old == nullptr){ ret = -EBADF; goto err; } - SymLink *symlink_inode_copy = new SymLink(*symlink_inode_old); + auto *symlink_inode_copy = new SymLink(*symlink_inode_old); copied_files.push_back((Inode*) symlink_inode_copy); } else { - special_inode_old = dynamic_cast(Inodes[i]); - if (special_inode_old == NULL){ + special_inode_old = dynamic_cast(i); + if (special_inode_old == nullptr){ ret = -EBADF; goto err; } - SpecialInode *special_inode_copy = new SpecialInode(*special_inode_old); + auto *special_inode_copy = new SpecialInode(*special_inode_old); copied_files.push_back((Inode*) special_inode_copy); } } @@ -200,22 +198,22 @@ int FuseRamFs::checkpoint(uint64_t key) void FuseRamFs::invalidate_kernel_states() { - for (std::vector::iterator it = Inodes.begin(); it != Inodes.end(); ++it){ - if ((*it) == nullptr){ + for (auto & it : Inodes){ + if (it == nullptr){ continue; } /* Invalidate possible kernel inode cache */ // if m_markedForDeletion is false (the inode exists and is not marked as deleted) - if (!(*it)->m_markedForDeletion){ - fuse_lowlevel_notify_inval_inode(ch, (*it)->GetIno(), 0, 0); + if (!it->m_markedForDeletion){ + fuse_lowlevel_notify_inval_inode(ch, it->GetIno(), 0, 0); } /* Invalidate potential d-cache */ - if(S_ISDIR((*it)->GetMode())){ - Directory *parent_dir = dynamic_cast(*it); + if(S_ISDIR(it->GetMode())){ + auto *parent_dir = dynamic_cast(it); /* If parent_dir has child dir*/ - for (auto it_child = parent_dir->m_children.begin(); it_child != parent_dir->m_children.end(); ++it_child){ - if (it_child->second > 0 && it_child->first != "." && it_child->first != ".."){ - fuse_lowlevel_notify_inval_entry(ch, (*it)->GetIno(), (it_child->first).c_str(), (it_child->first).size()); + for (auto & it_child : parent_dir->m_children){ + if (it_child.second > 0 && it_child.first != "." && it_child.first != ".."){ + fuse_lowlevel_notify_inval_entry(ch, it->GetIno(), (it_child.first).c_str(), (it_child.first).size()); } } } @@ -224,7 +222,7 @@ void FuseRamFs::invalidate_kernel_states() void FuseRamFs::check_restored_inode_size(){ - for (std::vector::iterator it = Inodes.begin() ; it != Inodes.end(); ++it){ + for (auto it = Inodes.begin() ; it != Inodes.end(); ++it){ std::cout << "Order: " << std::distance(Inodes.begin(), it) << " - Inode Size: " << (*it)->m_fuseEntryParam.attr.st_size << std::endl; } @@ -273,44 +271,44 @@ int FuseRamFs::restore(uint64_t key) SpecialInode *special_inode_stored; SymLink *symlink_inode_stored; - for (unsigned i = 0; i < stored_files.size(); i++) + for (auto & stored_file : stored_files) { - if (stored_files[i] == nullptr){ + if (stored_file == nullptr){ newfiles.push_back(nullptr); continue; } - inode_mode = stored_files[i]->GetMode(); + inode_mode = stored_file->GetMode(); if (S_ISREG(inode_mode)){ - file_inode_stored = dynamic_cast(stored_files[i]); - if (file_inode_stored == NULL){ + file_inode_stored = dynamic_cast(stored_file); + if (file_inode_stored == nullptr){ ret = -EBADF; goto err; } File *file_new = new File(* file_inode_stored); newfiles.push_back((Inode*) file_new); } else if (S_ISDIR(inode_mode)) { - dir_inode_stored = dynamic_cast(stored_files[i]); - if (dir_inode_stored == NULL){ + dir_inode_stored = dynamic_cast(stored_file); + if (dir_inode_stored == nullptr){ ret = -EBADF; goto err; } - Directory *dir_new = new Directory(*dir_inode_stored); + auto *dir_new = new Directory(*dir_inode_stored); newfiles.push_back((Inode*) dir_new); } else if (S_ISLNK(inode_mode)){ - symlink_inode_stored = dynamic_cast(stored_files[i]); - if (symlink_inode_stored == NULL){ + symlink_inode_stored = dynamic_cast(stored_file); + if (symlink_inode_stored == nullptr){ ret = -EBADF; goto err; } - SymLink *symlink_new = new SymLink(*symlink_inode_stored); + auto *symlink_new = new SymLink(*symlink_inode_stored); newfiles.push_back((Inode*) symlink_new); } else { - special_inode_stored = dynamic_cast(stored_files[i]); - if (special_inode_stored == NULL){ + special_inode_stored = dynamic_cast(stored_file); + if (special_inode_stored == nullptr){ ret = -EBADF; goto err; } - SpecialInode *special_inode_new = new SpecialInode(*special_inode_stored); + auto *special_inode_new = new SpecialInode(*special_inode_stored); newfiles.push_back((Inode*) special_inode_new); } } @@ -365,7 +363,7 @@ void FuseRamFs::FuseIoctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, break; } if (ret == 0) { - fuse_reply_ioctl(req, 0, NULL, 0); + fuse_reply_ioctl(req, 0, nullptr, 0); } else { fuse_reply_err(req, -ret); } @@ -405,7 +403,7 @@ void FuseRamFs::FuseInit(void *userdata, struct fuse_conn_info *conn) inode_p = new SpecialInode(SPECIAL_INODE_TYPE_NO_BLOCK); RegisterInode(inode_p, 0, 0, gid, uid); - Directory *root = new Directory(); + auto *root = new Directory(); // I think that that the root directory should have a hardlink count of 2. // This is what I believe I've surmised from reading around. @@ -449,8 +447,8 @@ void FuseRamFs::FuseLookup(fuse_req_t req, fuse_ino_t parent, const char *name) return; } - Directory *dir = dynamic_cast(parentInode); - if (dir == NULL) { + auto *dir = dynamic_cast(parentInode); + if (dir == nullptr) { // The parent wasn't a directory. It can't have any children. fuse_reply_err(req, ENOTDIR); return; @@ -554,7 +552,7 @@ void FuseRamFs::FuseOpenDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf } // You can't open a file with 'opendir'. Check for this. File *file = dynamic_cast(inode); - if (file != NULL) { + if (file != nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -585,7 +583,7 @@ void FuseRamFs::FuseReleaseDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_ } // You can't close a file with 'closedir'. Check for this. File *file = dynamic_cast(inode); - if (file != NULL) { + if (file != nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -620,8 +618,8 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, return; } - Directory *dir = dynamic_cast(inode); - if (dir == NULL) { + auto *dir = dynamic_cast(inode); + if (dir == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -630,7 +628,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, try { ctx = dir->PrepareReaddir(off); } catch (std::out_of_range &e) { - fuse_reply_buf(req, NULL, 0); + fuse_reply_buf(req, nullptr, 0); return; } @@ -649,13 +647,13 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, // This is why we access the children with an iterator (instead of using // some sort of index). - struct stat stbuf; + struct stat stbuf{}; memset(&stbuf, 0, sizeof(stbuf)); // Pick the lesser of the max response size or our max size. size_t bufSize = FuseRamFs::kReadDirBufSize < size ? FuseRamFs::kReadDirBufSize : size; char *buf = (char *) malloc(bufSize); - if (buf == NULL) { + if (buf == nullptr) { fuse_reply_err(req, ENOMEM); } @@ -717,8 +715,8 @@ void FuseRamFs::FuseOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info * } // You can't open a dir with 'open'. Check for this. - Directory *dir = dynamic_cast(inode); - if (dir != NULL) { + auto *dir = dynamic_cast(inode); + if (dir != nullptr) { fuse_reply_err(req, EISDIR); return; } @@ -743,8 +741,8 @@ void FuseRamFs::FuseRelease(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf } // You can't release a dir with 'close'. Check for this. - Directory *dir = dynamic_cast(inode_p); - if (dir != NULL) { + auto *dir = dynamic_cast(inode_p); + if (dir != nullptr) { fuse_reply_err(req, EISDIR); return; } @@ -778,8 +776,8 @@ void FuseRamFs::FuseFsyncDir(fuse_req_t req, fuse_ino_t ino, int datasync, struc } // You can only sync a dir with 'fsyncdir'. Check for this. - Directory *dir_p = dynamic_cast(inode_p); - if (dir_p == NULL) { + auto *dir_p = dynamic_cast(inode_p); + if (dir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -799,8 +797,8 @@ void FuseRamFs::FuseMknod(fuse_req_t req, fuse_ino_t parent, const char *name, } // You can only make something inside a directory - Directory *parentDir_p = dynamic_cast(parentInode); - if (parentDir_p == NULL) { + auto *parentDir_p = dynamic_cast(parentInode); + if (parentDir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -887,7 +885,7 @@ long FuseRamFs::do_create_node(Directory *parent, const char *name, mode_t mode, /* Special treatment for directories */ if (S_ISDIR(mode)) { /* Initialize the new directory: Add '.' and '..' */ - Directory *dir_p = dynamic_cast(new_node); + auto *dir_p = dynamic_cast(new_node); ret = dir_p->AddChild(string("."), ino); ret = dir_p->AddChild(string(".."), parent->GetIno()); } @@ -921,7 +919,7 @@ void FuseRamFs::FuseMkdir(fuse_req_t req, fuse_ino_t parent, const char *name, m } // You can only make something inside a directory - Directory *parentDir_p = dynamic_cast(parentInode); + auto *parentDir_p = dynamic_cast(parentInode); if (parentDir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; @@ -964,8 +962,8 @@ void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) } // You can only delete something inside a directory - Directory *parentDir_p = dynamic_cast(parentInode); - if (parentDir_p == NULL) { + auto *parentDir_p = dynamic_cast(parentInode); + if (parentDir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -1007,8 +1005,8 @@ void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) } // You can only delete something inside a directory - Directory *parentDir_p = dynamic_cast(parentInode); - if (parentDir_p == NULL) { + auto *parentDir_p = dynamic_cast(parentInode); + if (parentDir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -1038,8 +1036,8 @@ void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) return; } - Directory *dir_p = dynamic_cast(inode_p); - if (dir_p == NULL) { + auto *dir_p = dynamic_cast(inode_p); + if (dir_p == nullptr) { // Someone tried to rmdir on something that wasn't a directory. fuse_reply_err(req, ENOTDIR); return; @@ -1105,7 +1103,7 @@ void FuseRamFs::FuseWrite(fuse_req_t req, fuse_ino_t ino, const char *buf, size_ { std::shared_lock lk(crMutex); // TODO: Fuse seems to have problems writing with a null (buf) buffer. - if (buf == NULL) { + if (buf == nullptr) { fuse_reply_err(req, EINVAL); return; } @@ -1162,14 +1160,14 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, } // You can only rename something inside a directory - Directory *parentDir = dynamic_cast(parentInode); - if (parentDir == NULL) { + auto *parentDir = dynamic_cast(parentInode); + if (parentDir == nullptr) { fuse_reply_err(req, ENOTDIR); return; } - Directory *newParentDir = dynamic_cast(newParentInode); - if (newParentDir == NULL) { + auto *newParentDir = dynamic_cast(newParentInode); + if (newParentDir == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -1224,7 +1222,7 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, } /* If dest is a non-empty directory, return ENOTEMPTY */ if (S_ISDIR(existingInode->GetMode())) { - Directory *existingDir = dynamic_cast(existingInode); + auto *existingDir = dynamic_cast(existingInode); /* If the mode indicates a directory but it's not, something bad might have happened */ assert(existingDir); @@ -1286,8 +1284,8 @@ void FuseRamFs::FuseLink(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, c // The new parent must be a directory. TODO: Do we need this check? Will FUSE // ever give us a parent that isn't a dir? Test this. - Directory *parentDir = dynamic_cast(parent); - if (parentDir == NULL) { + auto *parentDir = dynamic_cast(parent); + if (parentDir == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -1325,8 +1323,8 @@ void FuseRamFs::FuseSymlink(fuse_req_t req, const char *link, fuse_ino_t parent, } // You can only make something inside a directory - Directory *dir = dynamic_cast(parent_p); - if (dir == NULL) { + auto *dir = dynamic_cast(parent_p); + if (dir == nullptr) { fuse_reply_err(req, ENOTDIR); return; } @@ -1372,8 +1370,8 @@ void FuseRamFs::FuseReadLink(fuse_req_t req, fuse_ino_t ino) } // You can only readlink on a symlink - SymLink *link_p = dynamic_cast(inode_p); - if (link_p == NULL) { + auto *link_p = dynamic_cast(inode_p); + if (link_p == nullptr) { fuse_reply_err(req, EINVAL); return; } @@ -1390,7 +1388,7 @@ void FuseRamFs::FuseReadLink(fuse_req_t req, fuse_ino_t ino) void FuseRamFs::FuseStatfs(fuse_req_t req, fuse_ino_t ino) { std::shared_lock lk(crMutex); - struct statvfs info; + struct statvfs info{}; FuseRamFs::FsStat(&info); fuse_reply_statfs(req, &info); } @@ -1484,8 +1482,8 @@ void FuseRamFs::FuseCreate(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_reply_err(req, ENOENT); return; } - Directory *parentDir_p = dynamic_cast(parent_p); - if (parentDir_p == NULL) { + auto *parentDir_p = dynamic_cast(parent_p); + if (parentDir_p == nullptr) { // The parent wasn't a directory. It can't have any children. fuse_reply_err(req, ENOTDIR); return; diff --git a/src/fuse_cpp_ramfs.hpp b/src/fuse_cpp_ramfs.hpp index aeea079..dc20056 100644 --- a/src/fuse_cpp_ramfs.hpp +++ b/src/fuse_cpp_ramfs.hpp @@ -143,7 +143,7 @@ class FuseRamFs { std::shared_lock readlk(inodesRwSem); try { return Inodes.at(ino); - } catch (std::out_of_range e) { + } catch (std::out_of_range& e) { return nullptr; } } diff --git a/src/inode.cpp b/src/inode.cpp index 850a392..a065dd3 100644 --- a/src/inode.cpp +++ b/src/inode.cpp @@ -292,13 +292,13 @@ size_t Inode::GetPickledSize() { // xattrs // a header telling how many xattrs there are res += sizeof(size_t); - for (auto it = m_xattr.begin(); it != m_xattr.end(); ++it) { + for (auto & it : m_xattr) { // xattr key: res += sizeof(size_t); - res += it->first.size(); + res += it.first.size(); // xattr value: res += sizeof(size_t); - res += it->second.second; + res += it.second.second; } return res; } @@ -324,11 +324,11 @@ size_t Inode::Pickle(void* &buf) { memcpy(ptr, &num_xattrs, sizeof(num_xattrs)); ptr += sizeof(num_xattrs); // pickle xattrs - for (auto it = m_xattr.begin(); it != m_xattr.end(); ++it) { - size_t keysize = it->first.size(); - const char *keystr = it->first.c_str(); - size_t valsize = it->second.second; - char *valdata = (char *)it->second.first; + for (auto & it : m_xattr) { + size_t keysize = it.first.size(); + const char *keystr = it.first.c_str(); + size_t valsize = it.second.second; + char *valdata = (char *)it.second.first; memcpy(ptr, &keysize, sizeof(keysize)); ptr += sizeof(keysize); memcpy(ptr, keystr, keysize); diff --git a/src/main.cpp b/src/main.cpp index 6812796..34bc746 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,14 +50,14 @@ int main(int argc, const char * argv[]) { if (options.subtype) { mountpoint = options.mountpoint; - if (mountpoint == NULL) { + if (mountpoint == nullptr) { cerr << "USAGE: fuse-cpp-ramfs MOUNTPOINT" << endl; - } else if ((ch = fuse_mount(mountpoint, &args)) != NULL) { + } else if ((ch = fuse_mount(mountpoint, &args)) != nullptr) { struct fuse_session *se; // The FUSE options come from our core code. - se = fuse_lowlevel_new(&args, &(core.FuseOps), - sizeof(core.FuseOps), NULL); - if (se != NULL) { + se = fuse_lowlevel_new(&args, &(FuseRamFs::FuseOps), + sizeof(FuseRamFs::FuseOps), nullptr); + if (se != nullptr) { fuse_daemonize(options.deamonize == 0); if (fuse_set_signal_handlers(se) != -1) { fuse_session_add_chan(se, ch); From 153cff919577b895a8ddd0c7e6d790be4598bca6 Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Sat, 31 Jul 2021 18:30:44 -0400 Subject: [PATCH 05/18] changed test script to pause before cleanup for debugging purposes --- src/pickle.cpp | 8 ++++---- tests/pkl_load_test.py | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pickle.cpp b/src/pickle.cpp index f5d722a..fa4ae71 100644 --- a/src/pickle.cpp +++ b/src/pickle.cpp @@ -326,16 +326,16 @@ ssize_t load_file_system(const void *data, std::vector& inodes, res = file->Load(ptr2); inodes.push_back(file); } else if (S_ISDIR(iinfo.mode)) { - Directory *dir = new Directory(); + auto *dir = new Directory(); res = dir->Load(ptr2); inodes.push_back(dir); } else if (S_ISLNK(iinfo.mode)) { - SymLink *link = new SymLink(); + auto *link = new SymLink(); res = link->Load(ptr2); inodes.push_back(link); } else if (S_ISCHR(iinfo.mode) || S_ISBLK(iinfo.mode) || S_ISSOCK(iinfo.mode) || S_ISFIFO(iinfo.mode) || iinfo.mode == 0) { - SpecialInode *special = new SpecialInode(); + auto *special = new SpecialInode(); res = special->Load(ptr2); inodes.push_back(special); } else { @@ -365,7 +365,7 @@ ssize_t load_file_system(const void *data, std::vector& inodes, } static size_t get_fsize(int fd) { - struct stat info; + struct stat info{}; int res = fstat(fd, &info); if (res < 0) { throw pickle_error(errno, __func__, __LINE__); diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py index 726a3fe..79f4cbb 100755 --- a/tests/pkl_load_test.py +++ b/tests/pkl_load_test.py @@ -18,7 +18,7 @@ '''*You need to comment out (rm -rf "$DIR") in racer script for this to work correctly''' racer_script_path = 'racer/racer.sh' '''range format: [a,b)''' -racer_duration = (3, 6) +racer_duration = (2, 4) racer_threads = (1, 2) num_test_attempts = (1, 2) # @@ -64,6 +64,7 @@ def pickle_save_signature(): def load_verify_signature(i): subprocess.run([load_path, path_to_fs, 'pickle_tmp{}'.format(i)]) signature = config_list[i] + time.sleep(1) new_signature = get_fs_signature() if new_signature == signature: print('loaded pickle file at index {} passed verification, signature: {}'.format(i, signature)) @@ -113,7 +114,7 @@ def perform_test(): pickle_save_signature() - time.sleep(3) + time.sleep(1) p = subprocess.Popen([racer_script_path, path_to_fs, @@ -146,6 +147,8 @@ def perform_test(): os.kill(pid, signal.SIGINT) # or SIGINT to CTRL_C_EVENT for Windows pass +input() + clean_exit() child.wait() From 8b925cf3633d3da27e4c4ecf4bc4e716c880b5a7 Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Mon, 2 Aug 2021 11:31:44 -0400 Subject: [PATCH 06/18] fix pickle memleak/update test script --- src/inode.cpp | 93 +++++++++++++++++++++--------------------- src/pickle.cpp | 41 ++++++++++--------- src/symlink.cpp | 10 ++--- tests/pkl_load_test.py | 25 +++++------- 4 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/inode.cpp b/src/inode.cpp index a065dd3..744c378 100644 --- a/src/inode.cpp +++ b/src/inode.cpp @@ -81,30 +81,31 @@ int Inode::ReplySetAttr(fuse_req_t req, struct stat *attr, int to_set) { m_fuseEntryParam.attr.st_flags = attr->st_flags; } #endif /* __APPLE__ */ - + // TODO: What do we do if this fails? Do we care? Log the event? #ifdef __APPLE__ clock_gettime(CLOCK_REALTIME, &(m_fuseEntryParam.attr.st_ctimespec)); #else clock_gettime(CLOCK_REALTIME, &(m_fuseEntryParam.attr.st_ctim)); #endif - + return fuse_reply_attr(req, &(m_fuseEntryParam.attr), 1.0); } void Inode::Forget(fuse_req_t req, unsigned long nlookup) { m_nlookup -= nlookup; - + fuse_reply_none(req); } -int Inode::SetXAttrAndReply(fuse_req_t req, const string &name, const void *value, size_t size, int flags, uint32_t position) { +int Inode::SetXAttrAndReply(fuse_req_t req, const string &name, const void *value, size_t size, int flags, + uint32_t position) { std::unique_lock lk(xattrRwSem); if (m_xattr.find(name) == m_xattr.end()) { if (flags & XATTR_CREATE) { return fuse_reply_err(req, EEXIST); } - + } else { if (flags & XATTR_REPLACE) { #ifdef __APPLE__ @@ -114,19 +115,19 @@ int Inode::SetXAttrAndReply(fuse_req_t req, const string &name, const void *valu #endif } } - + // TODO: What about overflow with size + position? size_t newExtent = size + position; - + // Expand the space for the value if required. if (m_xattr[name].second < newExtent) { void *newBuf = realloc(m_xattr[name].first, newExtent); if (newBuf == NULL) { return fuse_reply_err(req, E2BIG); } - + m_xattr[name].first = newBuf; - + // TODO: How does the user truncate the value? I.e., if they want to replace part, they'll send in // a position and a small size, right? If they want to make the whole thing shorter, then what? m_xattr[name].second = newExtent; @@ -134,7 +135,7 @@ int Inode::SetXAttrAndReply(fuse_req_t req, const string &name, const void *valu // Copy the data. memcpy((char *) m_xattr[name].first + position, value, size); - + return fuse_reply_err(req, 0); } @@ -147,29 +148,29 @@ int Inode::GetXAttrAndReply(fuse_req_t req, const string &name, size_t size, uin return fuse_reply_err(req, ENODATA); #endif } - + // The requestor wanted the size. TODO: How does position figure into this? if (size == 0) { return fuse_reply_xattr(req, m_xattr[name].second); } - + // TODO: What about overflow with size + position? size_t newExtent = size + position; - + // TODO: Is this the case where "the size is to small for the value"? if (m_xattr[name].second < newExtent) { return fuse_reply_err(req, ERANGE); } - + // TODO: It's fine for someone to just read part of a value, right (i.e. size is less than m_xattr[name].second)? return fuse_reply_buf(req, (char *) m_xattr[name].first + position, size); } int Inode::ListXAttrAndReply(fuse_req_t req, size_t size) { - + size_t listSize = 0; std::shared_lock lk(xattrRwSem); - for(map >::iterator it = m_xattr.begin(); it != m_xattr.end(); it++) { + for (map >::iterator it = m_xattr.begin(); it != m_xattr.end(); it++) { listSize += (it->first.size() + 1); } @@ -177,20 +178,20 @@ int Inode::ListXAttrAndReply(fuse_req_t req, size_t size) { if (size == 0) { return fuse_reply_xattr(req, listSize); } - + // "If the size is too small for the list, the ERANGE error should be sent" if (size < listSize) { return fuse_reply_err(req, ERANGE); } - + // TODO: Is EIO really the best error to return if we ran out of memory? void *buf = malloc(listSize); if (buf == NULL) { return fuse_reply_err(req, EIO); } - + size_t position = 0; - for(map >::iterator it = m_xattr.begin(); it != m_xattr.end(); it++) { + for (map >::iterator it = m_xattr.begin(); it != m_xattr.end(); it++) { // Copy the name as well as the null termination character. memcpy((char *) buf + position, it->first.c_str(), it->first.size() + 1); position += (it->first.size() + 1); @@ -198,7 +199,7 @@ int Inode::ListXAttrAndReply(fuse_req_t req, size_t size) { int retval = fuse_reply_buf(req, (char *) buf, position); free(buf); - + return retval; } @@ -212,9 +213,9 @@ int Inode::RemoveXAttrAndReply(fuse_req_t req, const string &name) { return fuse_reply_err(req, ENODATA); #endif } - + m_xattr.erase(it); - + return fuse_reply_err(req, 0); } @@ -223,37 +224,37 @@ int Inode::ReplyAccess(fuse_req_t req, int mask, gid_t gid, uid_t uid) { if (mask == F_OK) { return fuse_reply_err(req, 0); } - + std::shared_lock lk(entryRwSem); // Check other if ((m_fuseEntryParam.attr.st_mode & mask) == mask) { return fuse_reply_err(req, 0); } mask <<= 3; - + // Check group. TODO: What about other groups the user is in? if ((m_fuseEntryParam.attr.st_mode & mask) == mask) { // Go ahead if the user's main group is the same as the file's if (gid == m_fuseEntryParam.attr.st_gid) { return fuse_reply_err(req, 0); } - + // Now check the user's other groups. TODO: Where is this function?! not on this version of FUSE? // int numGroups = fuse_req_getgroups(req, 0, NULL); - + } mask <<= 3; - + // Check owner. if ((uid == m_fuseEntryParam.attr.st_uid) && (m_fuseEntryParam.attr.st_mode & mask) == mask) { return fuse_reply_err(req, 0); } - + return fuse_reply_err(req, EACCES); } void Inode::Initialize(fuse_ino_t ino, mode_t mode, nlink_t nlink, gid_t gid, uid_t uid) { - + // TODO: Still not sure if I should use m_fuseEntryParam = {} memset(&m_fuseEntryParam, 0, sizeof(m_fuseEntryParam)); m_fuseEntryParam.ino = ino; @@ -263,15 +264,15 @@ void Inode::Initialize(fuse_ino_t ino, mode_t mode, nlink_t nlink, gid_t gid, ui m_fuseEntryParam.attr.st_mode = mode; m_fuseEntryParam.attr.st_gid = gid; m_fuseEntryParam.attr.st_uid = uid; - + // Note this found on the Internet regarding nlink on dirs: // "For the root directory it is at least three; /, /., and /... Make a directory /foo and /foo/.. will have the same inode number as /, incrementing st_nlink. // // Cheers, Ralph." m_fuseEntryParam.attr.st_nlink = nlink; - + m_fuseEntryParam.attr.st_blksize = Inode::BufBlockSize; - + timespec ts; clock_gettime(CLOCK_REALTIME, &ts); #ifdef __APPLE__ @@ -292,7 +293,7 @@ size_t Inode::GetPickledSize() { // xattrs // a header telling how many xattrs there are res += sizeof(size_t); - for (auto & it : m_xattr) { + for (auto &it : m_xattr) { // xattr key: res += sizeof(size_t); res += it.first.size(); @@ -303,15 +304,15 @@ size_t Inode::GetPickledSize() { return res; } -size_t Inode::Pickle(void* &buf) { +size_t Inode::Pickle(void *&buf) { if (buf == nullptr) buf = malloc(GetPickledSize()); if (buf == nullptr) return 0; - - char *ptr = (char *)buf; + + char *ptr = (char *) buf; // bool m_markedForDeletion; - *ptr++ = m_markedForDeletion; + *ptr++ = m_markedForDeletion ? 1 : 0; // std::atomic_ulong m_nlookup; unsigned long nlookup = m_nlookup.load(); memcpy(ptr, &nlookup, sizeof(nlookup)); @@ -324,11 +325,11 @@ size_t Inode::Pickle(void* &buf) { memcpy(ptr, &num_xattrs, sizeof(num_xattrs)); ptr += sizeof(num_xattrs); // pickle xattrs - for (auto & it : m_xattr) { + for (auto &it : m_xattr) { size_t keysize = it.first.size(); const char *keystr = it.first.c_str(); size_t valsize = it.second.second; - char *valdata = (char *)it.second.first; + char *valdata = (char *) it.second.first; memcpy(ptr, &keysize, sizeof(keysize)); ptr += sizeof(keysize); memcpy(ptr, keystr, keysize); @@ -338,7 +339,7 @@ size_t Inode::Pickle(void* &buf) { memcpy(ptr, valdata, valsize); ptr += valsize; } - return (size_t)(ptr - (char *)buf); + return (size_t) (ptr - (char *) buf); } /* Inode pickle format: @@ -348,8 +349,8 @@ size_t Inode::Pickle(void* &buf) { * --xattr2_valsize--|-------xattr2_valdata-------|--xattr3_keysize--|--xattr3_...--|... */ -size_t Inode::Load(const void* &buf) { - const char *ptr = (const char *)buf; +size_t Inode::Load(const void *&buf) { + const char *ptr = (const char *) buf; // bool m_markedForDeletion m_markedForDeletion = *ptr++; // std::atomic_ulong m_nlookup; @@ -376,7 +377,7 @@ size_t Inode::Load(const void* &buf) { size_t valsize; memcpy(&valsize, ptr, sizeof(valsize)); ptr += sizeof(valsize); - char *value = (char *)malloc(valsize); + char *value = (char *) malloc(valsize); if (value == nullptr) goto error; memcpy(value, ptr, valsize); @@ -384,8 +385,8 @@ size_t Inode::Load(const void* &buf) { // add to xattrs tree m_xattr.insert({key, {value, valsize}}); } - return ptr - (char *)buf; -error: + return ptr - (char *) buf; + error: ClearXAttrs(); return 0; } \ No newline at end of file diff --git a/src/pickle.cpp b/src/pickle.cpp index fa4ae71..97580fd 100644 --- a/src/pickle.cpp +++ b/src/pickle.cpp @@ -26,7 +26,7 @@ class pickle_error : public std::exception { errnoname(_errno), _errno, func.c_str(), line); } - pickle_error(const pickle_error& other) { + pickle_error(const pickle_error &other) { _errno = other._errno; func = other.func; line = other.line; @@ -75,8 +75,8 @@ static inline size_t write_and_hash(int fd, SHA256_CTX *hashctx, return res; } -int pickle_file_system(int fd, std::vector& inodes, - std::queue& pending_delete_inodes, +int pickle_file_system(int fd, std::vector &inodes, + std::queue &pending_delete_inodes, struct statvfs &fs_stat, SHA256_CTX *hashctx) { /* Remember the current file cursor; * if pickling fails, move the cursor here. */ @@ -89,7 +89,7 @@ int pickle_file_system(int fd, std::vector& inodes, write_and_hash(fd, hashctx, &num_inodes, sizeof(num_inodes)); for (size_t i = 0; i < num_inodes; ++i) { Inode *inode = inodes[i]; - struct inode_state iinfo = {0}; + struct inode_state iinfo = {}; if (inode == nullptr) { iinfo.exist = false; write_and_hash(fd, hashctx, &iinfo, sizeof(iinfo)); @@ -106,6 +106,8 @@ int pickle_file_system(int fd, std::vector& inodes, iinfo.exist = true; write_and_hash(fd, hashctx, &iinfo, sizeof(iinfo)); write_and_hash(fd, hashctx, data, pickled_size); + + free(data); } // pickle the list of pending delete inodes size_t num_pending_delete = pending_delete_inodes.size(); @@ -151,7 +153,7 @@ int pickle_file_system(int fd, std::vector& inodes, write_and_hash(fd, hashctx, &stored_m_stbuf, sizeof(stored_m_stbuf)); }*/ - } catch (const pickle_error& e) { + } catch (const pickle_error &e) { lseek(fd, fpos, SEEK_SET); return -e.get_errno(); } @@ -163,7 +165,7 @@ static char *fetch_filepath(const char *cfgpath) { if (cfgfd < 0) throw pickle_error(errno, __func__, __LINE__); - char *path = (char *)calloc(PATH_MAX, 1); + char *path = (char *) calloc(PATH_MAX, 1); if (path == nullptr) { close(cfgfd); throw pickle_error(ENOMEM, __func__, __LINE__); @@ -174,9 +176,9 @@ static char *fetch_filepath(const char *cfgpath) { close(cfgfd); throw pickle_error(errno, __func__, __LINE__); } - + size_t pathlen = strnlen(path, PATH_MAX); - path = (char *)realloc(path, pathlen + 1); + path = (char *) realloc(path, pathlen + 1); close(cfgfd); return path; } @@ -300,10 +302,10 @@ int verify_state_file(int fd) { * * @return: bytes used */ -ssize_t load_file_system(const void *data, std::vector& inodes, - std::queue& pending_delete_inodes, - struct statvfs &fs_stat) { - const char *ptr = (const char *)data; +ssize_t load_file_system(const void *data, std::vector &inodes, + std::queue &pending_delete_inodes, + struct statvfs &fs_stat) { + const char *ptr = (const char *) data; try { // load statvfs memcpy(&fs_stat, ptr, sizeof(fs_stat)); @@ -320,7 +322,7 @@ ssize_t load_file_system(const void *data, std::vector& inodes, continue; size_t res; - const void *ptr2 = (const void *)ptr; + const void *ptr2 = (const void *) ptr; if (S_ISREG(iinfo.mode)) { File *file = new File(); res = file->Load(ptr2); @@ -334,7 +336,7 @@ ssize_t load_file_system(const void *data, std::vector& inodes, res = link->Load(ptr2); inodes.push_back(link); } else if (S_ISCHR(iinfo.mode) || S_ISBLK(iinfo.mode) || - S_ISSOCK(iinfo.mode) || S_ISFIFO(iinfo.mode) || iinfo.mode == 0) { + S_ISSOCK(iinfo.mode) || S_ISFIFO(iinfo.mode) || iinfo.mode == 0) { auto *special = new SpecialInode(); res = special->Load(ptr2); inodes.push_back(special); @@ -353,15 +355,14 @@ ssize_t load_file_system(const void *data, std::vector& inodes, for (size_t i = 0; i < num_pending_delete; ++i) { fuse_ino_t ino; memcpy(&ino, ptr, sizeof(ino)); - ptr += sizeof(ino); pending_delete_inodes.push(ino); + ptr += sizeof(ino); } - - } catch (const pickle_error& e) { + } catch (const pickle_error &e) { return -e.get_errno(); } - return ptr - (const char *)data; + return ptr - (const char *) data; } static size_t get_fsize(int fd) { @@ -406,7 +407,7 @@ int FuseRamFs::load_verifs2(void) { FuseRamFs::Inodes.clear(); while (!FuseRamFs::DeletedInodes.empty()) FuseRamFs::DeletedInodes.pop(); - char *ptr = (char *)mapped + sizeof(state_file_header); + char *ptr = (char *) mapped + sizeof(state_file_header); load_file_system(ptr, FuseRamFs::Inodes, FuseRamFs::DeletedInodes, FuseRamFs::m_stbuf); } catch (const pickle_error &e) { @@ -418,6 +419,6 @@ int FuseRamFs::load_verifs2(void) { close(fd); if (path) free(path); - + return res; } \ No newline at end of file diff --git a/src/symlink.cpp b/src/symlink.cpp index f294e56..308ae02 100644 --- a/src/symlink.cpp +++ b/src/symlink.cpp @@ -18,10 +18,10 @@ int SymLink::ReadAndReply(fuse_req_t req, size_t size, off_t off) { void SymLink::Initialize(fuse_ino_t ino, mode_t mode, nlink_t nlink, gid_t gid, uid_t uid) { Inode::Initialize(ino, mode, nlink, gid, uid); - + m_fuseEntryParam.attr.st_size = m_link.size(); m_fuseEntryParam.attr.st_blocks = m_fuseEntryParam.attr.st_size / m_fuseEntryParam.attr.st_blksize; - + // Add another block if the size is larger than a whole number of blocks if (m_fuseEntryParam.attr.st_blksize * m_fuseEntryParam.attr.st_blocks < m_fuseEntryParam.attr.st_size) { m_fuseEntryParam.attr.st_blocks++; @@ -32,7 +32,7 @@ size_t SymLink::GetPickledSize() { return Inode::GetPickledSize() + m_link.size(); } -size_t SymLink::Pickle(void* &buf) { +size_t SymLink::Pickle(void *&buf) { if (buf == nullptr) { buf = malloc(SymLink::GetPickledSize()); } @@ -45,9 +45,9 @@ size_t SymLink::Pickle(void* &buf) { return offset + m_link.size(); } -size_t SymLink::Load(const void* &buf) { +size_t SymLink::Load(const void *&buf) { size_t offset = Inode::Load(buf); - const char *ptr = (const char *)buf + offset; + const char *ptr = (const char *) buf + offset; size_t linksize = m_fuseEntryParam.attr.st_size; m_link = std::string(ptr, linksize); return offset + linksize; diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py index 79f4cbb..c72e1cc 100755 --- a/tests/pkl_load_test.py +++ b/tests/pkl_load_test.py @@ -10,7 +10,7 @@ from contextlib import suppress # config -fs_name = 'fuse-cpp-ramfs' +fs_exec = 'fuse-cpp-ramfs' # bin program or path, ex: ../../verifs1/crmfs path_to_fs = '{}/mnt/fuse-cpp-ramfs'.format(os.getcwd()) # absolute path only absfs_path = '../../fs-state/absfs' pkl_path = '../build/pkl' @@ -18,8 +18,8 @@ '''*You need to comment out (rm -rf "$DIR") in racer script for this to work correctly''' racer_script_path = 'racer/racer.sh' '''range format: [a,b)''' -racer_duration = (2, 4) -racer_threads = (1, 2) +racer_duration = (3, 7) +racer_threads = (3, 5) num_test_attempts = (1, 2) # @@ -112,16 +112,11 @@ def perform_test(): p.wait() - pickle_save_signature() - - time.sleep(1) + input('make sure racer threads are terminated and press any button to continue:') - p = subprocess.Popen([racer_script_path, - path_to_fs, - str(get_random_in_range(racer_duration)), - str(get_random_in_range(racer_threads))]) + pickle_save_signature() - p.wait() + input('press any button to load the pickled file:') load_verify_signature(size - 1) @@ -132,23 +127,25 @@ def perform_test(): clean_files('', path_to_fs) -child = subprocess.Popen([fs_name, +child = subprocess.Popen([fs_exec, path_to_fs]) time.sleep(1) try: perform_test() + input() +except KeyboardInterrupt: + pass except Exception as err: print(err) if p is not None: pid = p.pid with suppress(Exception): os.kill(pid, signal.SIGINT) # or SIGINT to CTRL_C_EVENT for Windows + input() pass -input() - clean_exit() child.wait() From 8b5ac1ccb25d85588ceebd86a9ad5d5821cb7875 Mon Sep 17 00:00:00 2001 From: peiliou Date: Wed, 11 Aug 2021 19:43:28 -0400 Subject: [PATCH 07/18] make test script fully automatic --- tests/pkl_load_test.py | 81 ++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py index c72e1cc..3c87d55 100755 --- a/tests/pkl_load_test.py +++ b/tests/pkl_load_test.py @@ -7,6 +7,7 @@ import errno import random import signal +import psutil from contextlib import suppress # config @@ -18,16 +19,19 @@ '''*You need to comment out (rm -rf "$DIR") in racer script for this to work correctly''' racer_script_path = 'racer/racer.sh' '''range format: [a,b)''' -racer_duration = (3, 7) -racer_threads = (3, 5) -num_test_attempts = (1, 2) +racer_duration = (1, 5) +racer_threads = (3, 7) +num_test_attempts = (5, 10) # print(sys.platform) config_list = [] size = 0 +success_count = 0 p = None +child = None +random_num_attempts = random.randrange(num_test_attempts[0], num_test_attempts[1]) def get_random_in_range(range_tpl): @@ -44,11 +48,18 @@ def make_sure_path_exists(path): def get_fs_signature(): p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) - p2 = subprocess.Popen(['awk', 'END{print $NF}'], stdin=p1.stdout, stdout=subprocess.PIPE) - signature = p2.communicate()[0] - if signature == b'iterating...\n': - p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) - raise Exception(p1.communicate()[0]) + raw_res = p1.communicate()[0] + signature = raw_res.rsplit(b' ', 1)[1] + while signature == b'iterating...\n': + if b'cannot stat' in raw_res: + print('encountered false-positive while calculating the signature, retrying in 5 sec...') + time.sleep(5) + p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) + raw_res = p1.communicate()[0] + signature = raw_res.rsplit(b' ', 1)[1] + continue + else: + raise Exception(raw_res) return signature @@ -62,14 +73,17 @@ def pickle_save_signature(): def load_verify_signature(i): + global success_count + subprocess.run([load_path, path_to_fs, 'pickle_tmp{}'.format(i)]) signature = config_list[i] - time.sleep(1) + time.sleep(3) new_signature = get_fs_signature() if new_signature == signature: print('loaded pickle file at index {} passed verification, signature: {}'.format(i, signature)) + success_count += 1 else: - raise Exception('signature at index {} has a discrepancy: {} -> {}'.format(i, signature, new_signature)) + print('signature at index {} has a discrepancy: {} -> {}'.format(i, signature, new_signature)) def clean_files(prefix, cwd=None): @@ -82,7 +96,7 @@ def run(cmd, cwd=path_to_fs): subprocess.run(cmd, cwd=cwd) -def clean_exit(): +def unmount(): time.sleep(1) # If you unmount too soon, the mountpoint won't be available. if sys.platform == 'darwin' or sys.platform == 'linux': @@ -92,19 +106,35 @@ def clean_exit(): subprocess.run(['fusermount', '-u', path_to_fs]) + +def clean_exit(): + unmount() + print('perform cleanup......') for fl in glob.glob('pickle_tmp*'): os.remove(fl) +def wait_for_process(name): + while name in (i.name() for i in psutil.process_iter()): + print('waiting for {} to terminate......'.format(name)) + time.sleep(5) + time.sleep(1) + + # =================================================== def perform_test(): - global p - for i in range(get_random_in_range(num_test_attempts)): - time.sleep(3) + global p, child, random_num_attempts + for i in range(random_num_attempts): + child = subprocess.Popen([fs_exec, + path_to_fs]) + time.sleep(1) + + wait_for_process("dd") + p = subprocess.Popen([racer_script_path, path_to_fs, str(get_random_in_range(racer_duration)), @@ -112,14 +142,26 @@ def perform_test(): p.wait() - input('make sure racer threads are terminated and press any button to continue:') + wait_for_process("dd") pickle_save_signature() - input('press any button to load the pickled file:') + wait_for_process("dd") + + p = subprocess.Popen([racer_script_path, + path_to_fs, + str(get_random_in_range(racer_duration)), + str(get_random_in_range(racer_threads))]) + + p.wait() + + wait_for_process("dd") load_verify_signature(size - 1) + time.sleep(1) + unmount() + # =================================================== @@ -127,14 +169,9 @@ def perform_test(): clean_files('', path_to_fs) -child = subprocess.Popen([fs_exec, - path_to_fs]) - -time.sleep(1) - try: perform_test() - input() + print("Test Complete,Success: {}/{}\n-----------------------------".format(success_count, random_num_attempts)) except KeyboardInterrupt: pass except Exception as err: From 46f92407de05206cc4c943d5326fc88c13e27877 Mon Sep 17 00:00:00 2001 From: peiliou Date: Sun, 22 Aug 2021 23:01:38 -0400 Subject: [PATCH 08/18] complete implementation&fix of verifs2 pickle/unpickle(with checkpoint/restore pickle support) --- src/cr_util.cpp | 63 ++--- src/cr_util.hpp | 10 +- src/directory.cpp | 1 + src/fuse_cpp_ramfs.cpp | 509 +++++++++++++++++++---------------------- src/inode.cpp | 2 + src/pickle.cpp | 116 +++++++++- tests/pkl_load_test.py | 189 --------------- 7 files changed, 391 insertions(+), 499 deletions(-) delete mode 100755 tests/pkl_load_test.py diff --git a/src/cr_util.cpp b/src/cr_util.cpp index 8c78ca6..12e6a9d 100644 --- a/src/cr_util.cpp +++ b/src/cr_util.cpp @@ -11,41 +11,46 @@ bool isExistInDeleted(fuse_ino_t curr_ino, std::queue DeletedInodes) void print_ino_queue(std::queue DeletedInodes); #endif -std::unordered_map state_pool; +std::unordered_map state_pool; + +int insert_state(uint64_t key, + const std::tuple, std::queue, + struct statvfs> &fs_states_vec) { + auto it = state_pool.find(key); + if (it != state_pool.end()) { + return -EEXIST; + } + state_pool.insert({key, fs_states_vec}); -int insert_state(uint64_t key, - const std::tuple, std::queue, - struct statvfs>& fs_states_vec) -{ - auto it = state_pool.find(key); - if (it != state_pool.end()) { - return -EEXIST; - } - state_pool.insert({key, fs_states_vec}); + return 0; +} - return 0; +verifs2_state find_state(uint64_t key) { + auto it = state_pool.find(key); + if (it == state_pool.end()) { + std::queue empty_queue; + struct statvfs empty_statvfs = {}; + return verifs2_state{std::vector(), empty_queue, empty_statvfs}; + } else { + return it->second; + } } -verifs2_state find_state(uint64_t key) -{ - auto it = state_pool.find(key); - if (it == state_pool.end()) { - std::queue empty_queue; - struct statvfs empty_statvfs = {}; - return verifs2_state{std::vector (), empty_queue, empty_statvfs}; - } else { - return it->second; - } +int remove_state(uint64_t key) { + auto it = state_pool.find(key); + if (it == state_pool.end()) { + return -ENOENT; + } + state_pool.erase(it); + return 0; } -int remove_state(uint64_t key) -{ - auto it = state_pool.find(key); - if (it == state_pool.end()) { - return -ENOENT; - } - state_pool.erase(it); - return 0; +std::unordered_map get_state_pool() { + return state_pool; +} + +void clear_states() { + state_pool.clear(); } #ifdef DUMP_TESTING diff --git a/src/cr_util.hpp b/src/cr_util.hpp index d2d3596..0afd279 100644 --- a/src/cr_util.hpp +++ b/src/cr_util.hpp @@ -7,12 +7,18 @@ #include "special_inode.hpp" #include "symlink.hpp" -typedef std::tuple, std::queue, struct statvfs> verifs2_state; +typedef std::tuple, std::queue, struct statvfs> verifs2_state; + +int insert_state(uint64_t key, const verifs2_state &fs_states_vec); -int insert_state(uint64_t key, const verifs2_state& fs_states_vec); verifs2_state find_state(uint64_t key); + int remove_state(uint64_t key); +std::unordered_map get_state_pool(); + +void clear_states(); + #ifdef DUMP_TESTING void dump_File(File* file); void dump_Directory(Directory* dir); diff --git a/src/directory.cpp b/src/directory.cpp index 52beec8..461760c 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -244,6 +244,7 @@ size_t Directory::Load(const void* &buf) { size_t nchildren; memcpy(&nchildren, ptr, sizeof(nchildren)); ptr += sizeof(nchildren); + m_children.clear(); // iterate the list and load the children for (size_t i = 0; i < nchildren; ++i) { // load inode number diff --git a/src/fuse_cpp_ramfs.cpp b/src/fuse_cpp_ramfs.cpp index 6a07c32..26c2893 100644 --- a/src/fuse_cpp_ramfs.cpp +++ b/src/fuse_cpp_ramfs.cpp @@ -43,42 +43,41 @@ std::mutex FuseRamFs::renameMutex; struct fuse_lowlevel_ops FuseRamFs::FuseOps = {}; -FuseRamFs::FuseRamFs(fsblkcnt_t blocks, fsfilcnt_t inodes) -{ - FuseOps.init = FuseRamFs::FuseInit; - FuseOps.destroy = FuseRamFs::FuseDestroy; - FuseOps.lookup = FuseRamFs::FuseLookup; - FuseOps.forget = FuseRamFs::FuseForget; - FuseOps.getattr = FuseRamFs::FuseGetAttr; - FuseOps.setattr = FuseRamFs::FuseSetAttr; - FuseOps.readlink = FuseRamFs::FuseReadLink; - FuseOps.mknod = FuseRamFs::FuseMknod; - FuseOps.mkdir = FuseRamFs::FuseMkdir; - FuseOps.unlink = FuseRamFs::FuseUnlink; - FuseOps.rmdir = FuseRamFs::FuseRmdir; - FuseOps.symlink = FuseRamFs::FuseSymlink; - FuseOps.rename = FuseRamFs::FuseRename; - FuseOps.link = FuseRamFs::FuseLink; - FuseOps.open = FuseRamFs::FuseOpen; - FuseOps.read = FuseRamFs::FuseRead; - FuseOps.write = FuseRamFs::FuseWrite; - FuseOps.flush = FuseRamFs::FuseFlush; - FuseOps.release = FuseRamFs::FuseRelease; - FuseOps.fsync = FuseRamFs::FuseFsync; - FuseOps.opendir = FuseRamFs::FuseOpenDir; - FuseOps.readdir = FuseRamFs::FuseReadDir; - FuseOps.releasedir = FuseRamFs::FuseReleaseDir; - FuseOps.fsyncdir = FuseRamFs::FuseFsyncDir; - FuseOps.statfs = FuseRamFs::FuseStatfs; - FuseOps.setxattr = FuseRamFs::FuseSetXAttr; - FuseOps.getxattr = FuseRamFs::FuseGetXAttr; - FuseOps.listxattr = FuseRamFs::FuseListXAttr; +FuseRamFs::FuseRamFs(fsblkcnt_t blocks, fsfilcnt_t inodes) { + FuseOps.init = FuseRamFs::FuseInit; + FuseOps.destroy = FuseRamFs::FuseDestroy; + FuseOps.lookup = FuseRamFs::FuseLookup; + FuseOps.forget = FuseRamFs::FuseForget; + FuseOps.getattr = FuseRamFs::FuseGetAttr; + FuseOps.setattr = FuseRamFs::FuseSetAttr; + FuseOps.readlink = FuseRamFs::FuseReadLink; + FuseOps.mknod = FuseRamFs::FuseMknod; + FuseOps.mkdir = FuseRamFs::FuseMkdir; + FuseOps.unlink = FuseRamFs::FuseUnlink; + FuseOps.rmdir = FuseRamFs::FuseRmdir; + FuseOps.symlink = FuseRamFs::FuseSymlink; + FuseOps.rename = FuseRamFs::FuseRename; + FuseOps.link = FuseRamFs::FuseLink; + FuseOps.open = FuseRamFs::FuseOpen; + FuseOps.read = FuseRamFs::FuseRead; + FuseOps.write = FuseRamFs::FuseWrite; + FuseOps.flush = FuseRamFs::FuseFlush; + FuseOps.release = FuseRamFs::FuseRelease; + FuseOps.fsync = FuseRamFs::FuseFsync; + FuseOps.opendir = FuseRamFs::FuseOpenDir; + FuseOps.readdir = FuseRamFs::FuseReadDir; + FuseOps.releasedir = FuseRamFs::FuseReleaseDir; + FuseOps.fsyncdir = FuseRamFs::FuseFsyncDir; + FuseOps.statfs = FuseRamFs::FuseStatfs; + FuseOps.setxattr = FuseRamFs::FuseSetXAttr; + FuseOps.getxattr = FuseRamFs::FuseGetXAttr; + FuseOps.listxattr = FuseRamFs::FuseListXAttr; FuseOps.removexattr = FuseRamFs::FuseRemoveXAttr; - FuseOps.access = FuseRamFs::FuseAccess; - FuseOps.create = FuseRamFs::FuseCreate; - FuseOps.getlk = FuseRamFs::FuseGetLock; - FuseOps.ioctl = FuseRamFs::FuseIoctl; - + FuseOps.access = FuseRamFs::FuseAccess; + FuseOps.create = FuseRamFs::FuseCreate; + FuseOps.getlk = FuseRamFs::FuseGetLock; + FuseOps.ioctl = FuseRamFs::FuseIoctl; + if (blocks <= 0) { blocks = kTotalBlocks; } @@ -87,39 +86,36 @@ FuseRamFs::FuseRamFs(fsblkcnt_t blocks, fsfilcnt_t inodes) } /* No need for locking because no other threads should * be accessing these attributes during construction */ - m_stbuf.f_bsize = Inode::BufBlockSize; /* File system block size */ - m_stbuf.f_frsize = Inode::BufBlockSize; /* Fundamental file system block size */ - m_stbuf.f_blocks = blocks; /* Blocks on FS in units of f_frsize */ - m_stbuf.f_bfree = blocks; /* Free blocks */ - m_stbuf.f_bavail = blocks; /* Blocks available to non-root */ - m_stbuf.f_files = inodes; /* Total inodes */ - m_stbuf.f_ffree = inodes; /* Free inodes */ - m_stbuf.f_favail = inodes; /* Free inodes for non-root */ - m_stbuf.f_fsid = kFilesystemId; /* Filesystem ID */ - m_stbuf.f_flag = 0; /* Bit mask of values */ + m_stbuf.f_bsize = Inode::BufBlockSize; /* File system block size */ + m_stbuf.f_frsize = Inode::BufBlockSize; /* Fundamental file system block size */ + m_stbuf.f_blocks = blocks; /* Blocks on FS in units of f_frsize */ + m_stbuf.f_bfree = blocks; /* Free blocks */ + m_stbuf.f_bavail = blocks; /* Blocks available to non-root */ + m_stbuf.f_files = inodes; /* Total inodes */ + m_stbuf.f_ffree = inodes; /* Free inodes */ + m_stbuf.f_favail = inodes; /* Free inodes for non-root */ + m_stbuf.f_fsid = kFilesystemId; /* Filesystem ID */ + m_stbuf.f_flag = 0; /* Bit mask of values */ m_stbuf.f_namemax = kMaxFilenameLength; /* Max file name length */ } -FuseRamFs::~FuseRamFs() -{ +FuseRamFs::~FuseRamFs() { } -static void free_inodes(std::vector &table) -{ - for (auto & i : table) { - delete i; +static void free_inodes(std::vector &table) { + for (auto &i : table) { + delete i; } table.clear(); } -int FuseRamFs::checkpoint(uint64_t key) -{ +int FuseRamFs::checkpoint(uint64_t key) { //std::cout << "Start Checkpoint.\n"; // Lock std::unique_lock lk(crMutex); int ret = 0; - std::vector copied_files = std::vector(); + std::vector copied_files = std::vector(); mode_t inode_mode; @@ -128,58 +124,57 @@ int FuseRamFs::checkpoint(uint64_t key) SpecialInode *special_inode_old; SymLink *symlink_inode_old; - for (auto & i : Inodes) - { - if (i == nullptr){ + for (auto &i : Inodes) { + if (i == nullptr) { copied_files.push_back(nullptr); continue; } inode_mode = i->GetMode(); - if (S_ISREG(inode_mode)){ + if (S_ISREG(inode_mode)) { file_inode_old = dynamic_cast(i); - if (file_inode_old == nullptr){ + if (file_inode_old == nullptr) { ret = -EBADF; goto err; } File *file_inode_copy = new File(*file_inode_old); - copied_files.push_back((Inode*) file_inode_copy); + copied_files.push_back((Inode *) file_inode_copy); } else if (S_ISDIR(inode_mode)) { dir_inode_old = dynamic_cast(i); - if (dir_inode_old == nullptr){ + if (dir_inode_old == nullptr) { ret = -EBADF; goto err; } auto *dir_copy = new Directory(*dir_inode_old); - copied_files.push_back((Inode*) dir_copy); + copied_files.push_back((Inode *) dir_copy); } else if (S_ISLNK(inode_mode)) { symlink_inode_old = dynamic_cast(i); - if (symlink_inode_old == nullptr){ + if (symlink_inode_old == nullptr) { ret = -EBADF; goto err; } auto *symlink_inode_copy = new SymLink(*symlink_inode_old); - copied_files.push_back((Inode*) symlink_inode_copy); + copied_files.push_back((Inode *) symlink_inode_copy); } else { special_inode_old = dynamic_cast(i); - if (special_inode_old == nullptr){ + if (special_inode_old == nullptr) { ret = -EBADF; goto err; } auto *special_inode_copy = new SpecialInode(*special_inode_old); - copied_files.push_back((Inode*) special_inode_copy); - } + copied_files.push_back((Inode *) special_inode_copy); + } } // insert state ret = insert_state(key, std::make_tuple(copied_files, DeletedInodes, m_stbuf)); - if (ret != 0){ + if (ret != 0) { goto err; } #ifdef DUMP_TESTING @@ -189,31 +184,31 @@ int FuseRamFs::checkpoint(uint64_t key) } #endif return ret; -err: + err: // clear copied_files vector std::cerr << "Checkpointing went to error.\n"; free_inodes(copied_files); return ret; } -void FuseRamFs::invalidate_kernel_states() -{ - for (auto & it : Inodes){ - if (it == nullptr){ +void FuseRamFs::invalidate_kernel_states() { + for (auto &it : Inodes) { + if (it == nullptr) { continue; } /* Invalidate possible kernel inode cache */ // if m_markedForDeletion is false (the inode exists and is not marked as deleted) - if (!it->m_markedForDeletion){ + if (!it->m_markedForDeletion) { fuse_lowlevel_notify_inval_inode(ch, it->GetIno(), 0, 0); } /* Invalidate potential d-cache */ - if(S_ISDIR(it->GetMode())){ + if (S_ISDIR(it->GetMode())) { auto *parent_dir = dynamic_cast(it); /* If parent_dir has child dir*/ - for (auto & it_child : parent_dir->m_children){ - if (it_child.second > 0 && it_child.first != "." && it_child.first != ".."){ - fuse_lowlevel_notify_inval_entry(ch, it->GetIno(), (it_child.first).c_str(), (it_child.first).size()); + for (auto &it_child : parent_dir->m_children) { + if (it_child.second > 0 && it_child.first != "." && it_child.first != "..") { + fuse_lowlevel_notify_inval_entry(ch, it->GetIno(), (it_child.first).c_str(), + (it_child.first).size()); } } } @@ -221,15 +216,14 @@ void FuseRamFs::invalidate_kernel_states() } -void FuseRamFs::check_restored_inode_size(){ - for (auto it = Inodes.begin() ; it != Inodes.end(); ++it){ - std::cout << "Order: " << std::distance(Inodes.begin(), it) << " - Inode Size: " - << (*it)->m_fuseEntryParam.attr.st_size << std::endl; +void FuseRamFs::check_restored_inode_size() { + for (auto it = Inodes.begin(); it != Inodes.end(); ++it) { + std::cout << "Order: " << std::distance(Inodes.begin(), it) << " - Inode Size: " + << (*it)->m_fuseEntryParam.attr.st_size << std::endl; } } -int FuseRamFs::restore(uint64_t key) -{ +int FuseRamFs::restore(uint64_t key) { //std::cout << "Start Restore.\n"; // Lock std::unique_lock lk(crMutex); @@ -243,11 +237,11 @@ int FuseRamFs::restore(uint64_t key) #endif verifs2_state stored_states = find_state(key); - std::vector stored_files = std::get<0>(stored_states); + std::vector stored_files = std::get<0>(stored_states); std::queue stored_DeletedInodes = std::get<1>(stored_states); struct statvfs stored_m_stbuf = std::get<2>(stored_states); - if (stored_files.empty() && stored_DeletedInodes.empty()){ + if (stored_files.empty() && stored_DeletedInodes.empty()) { ret = -ENOENT; std::cerr << "Not found state in state pool with key " << key << std::endl; return ret; @@ -263,7 +257,7 @@ int FuseRamFs::restore(uint64_t key) struct statvfs tmp_m_stbuf = m_stbuf; m_stbuf = stored_m_stbuf; - std::vector newfiles; + std::vector newfiles; mode_t inode_mode; File *file_inode_stored; @@ -271,45 +265,44 @@ int FuseRamFs::restore(uint64_t key) SpecialInode *special_inode_stored; SymLink *symlink_inode_stored; - for (auto & stored_file : stored_files) - { - if (stored_file == nullptr){ + for (auto &stored_file : stored_files) { + if (stored_file == nullptr) { newfiles.push_back(nullptr); continue; } inode_mode = stored_file->GetMode(); - if (S_ISREG(inode_mode)){ + if (S_ISREG(inode_mode)) { file_inode_stored = dynamic_cast(stored_file); - if (file_inode_stored == nullptr){ + if (file_inode_stored == nullptr) { ret = -EBADF; goto err; } - File *file_new = new File(* file_inode_stored); - newfiles.push_back((Inode*) file_new); + File *file_new = new File(*file_inode_stored); + newfiles.push_back((Inode *) file_new); } else if (S_ISDIR(inode_mode)) { dir_inode_stored = dynamic_cast(stored_file); - if (dir_inode_stored == nullptr){ + if (dir_inode_stored == nullptr) { ret = -EBADF; goto err; } auto *dir_new = new Directory(*dir_inode_stored); - newfiles.push_back((Inode*) dir_new); - } else if (S_ISLNK(inode_mode)){ + newfiles.push_back((Inode *) dir_new); + } else if (S_ISLNK(inode_mode)) { symlink_inode_stored = dynamic_cast(stored_file); - if (symlink_inode_stored == nullptr){ + if (symlink_inode_stored == nullptr) { ret = -EBADF; goto err; } auto *symlink_new = new SymLink(*symlink_inode_stored); - newfiles.push_back((Inode*) symlink_new); + newfiles.push_back((Inode *) symlink_new); } else { special_inode_stored = dynamic_cast(stored_file); - if (special_inode_stored == nullptr){ + if (special_inode_stored == nullptr) { ret = -EBADF; goto err; } auto *special_inode_new = new SpecialInode(*special_inode_stored); - newfiles.push_back((Inode*) special_inode_new); + newfiles.push_back((Inode *) special_inode_new); } } // clear old Inodes @@ -326,7 +319,7 @@ int FuseRamFs::restore(uint64_t key) } #endif return 0; -err: + err: std::cerr << "Restoration went to error.\n"; free_inodes(newfiles); std::vector().swap(newfiles); @@ -336,17 +329,16 @@ int FuseRamFs::restore(uint64_t key) } void FuseRamFs::FuseIoctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, - struct fuse_file_info *fi, unsigned flags, - const void *in_buf, size_t in_bufsz, size_t out_bufsz) -{ + struct fuse_file_info *fi, unsigned flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) { int ret; - switch (cmd){ + switch (cmd) { case VERIFS_CHECKPOINT: - ret = checkpoint((uint64_t)arg); + ret = checkpoint((uint64_t) arg); break; - + case VERIFS_RESTORE: - ret = restore((uint64_t)arg); + ret = restore((uint64_t) arg); break; case VERIFS_PICKLE: @@ -356,7 +348,7 @@ void FuseRamFs::FuseIoctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, case VERIFS_LOAD: ret = load_verifs2(); break; - + default: std::cerr << "Function Not implemented in FuseIoctl.\n"; ret = ENOSYS; @@ -382,29 +374,28 @@ static inline mode_t get_umask() { @param userdata Any user data carried through FUSE calls. @param conn Information on the capabilities of the connection to FUSE. */ -void FuseRamFs::FuseInit(void *userdata, struct fuse_conn_info *conn) -{ +void FuseRamFs::FuseInit(void *userdata, struct fuse_conn_info *conn) { /* No need for locking because no other threads should be * accessing these elements during f/s initialization */ - m_stbuf.f_bfree = m_stbuf.f_blocks; /* Free blocks */ - m_stbuf.f_bavail = m_stbuf.f_blocks; /* Blocks available to non-root */ - m_stbuf.f_ffree = m_stbuf.f_files; /* Free inodes */ - m_stbuf.f_favail = m_stbuf.f_files; /* Free inodes for non-root */ - m_stbuf.f_flag = 0; /* Bit mask of values */ - + m_stbuf.f_bfree = m_stbuf.f_blocks; /* Free blocks */ + m_stbuf.f_bavail = m_stbuf.f_blocks; /* Blocks available to non-root */ + m_stbuf.f_ffree = m_stbuf.f_files; /* Free inodes */ + m_stbuf.f_favail = m_stbuf.f_files; /* Free inodes for non-root */ + m_stbuf.f_flag = 0; /* Bit mask of values */ + // We start out with a special inode and a single directory (the root directory). Inode *inode_p; - + // For our root nodes, we'll set gid and uid to the ones the process is using. uid_t gid = getgid(); - + // TODO: Should I be getting the effective UID instead? uid_t uid = getuid(); inode_p = new SpecialInode(SPECIAL_INODE_TYPE_NO_BLOCK); RegisterInode(inode_p, 0, 0, gid, uid); - + auto *root = new Directory(); - + // I think that that the root directory should have a hardlink count of 2. // This is what I believe I've surmised from reading around. mode_t rootmode = 0777 & (~get_umask()); @@ -422,10 +413,9 @@ void FuseRamFs::FuseInit(void *userdata, struct fuse_conn_info *conn) @param userdata Any user data carried through FUSE calls. */ -void FuseRamFs::FuseDestroy(void *userdata) -{ +void FuseRamFs::FuseDestroy(void *userdata) { /* No need for locking because it's destruction of the file system */ - for(auto const& inode: Inodes) { + for (auto const &inode: Inodes) { delete inode; } } @@ -438,8 +428,7 @@ void FuseRamFs::FuseDestroy(void *userdata) @param parent The parent inode. @param name The name of the child to look up. */ -void FuseRamFs::FuseLookup(fuse_req_t req, fuse_ino_t parent, const char *name) -{ +void FuseRamFs::FuseLookup(fuse_req_t req, fuse_ino_t parent, const char *name) { std::shared_lock lk(crMutex); Inode *parentInode = GetInode(parent); if (parentInode == nullptr || parentInode->HasNoLinks()) { @@ -453,13 +442,13 @@ void FuseRamFs::FuseLookup(fuse_req_t req, fuse_ino_t parent, const char *name) fuse_reply_err(req, ENOTDIR); return; } - + fuse_ino_t ino = dir->ChildInodeNumberWithName(string(name)); if (ino == INO_NOTFOUND) { fuse_reply_err(req, ENOENT); return; } - + Inode *inode = GetInode(ino); /* Return ENOENT if this inode has been deleted */ if (inode == nullptr || inode->HasNoLinks()) { @@ -477,8 +466,7 @@ void FuseRamFs::FuseLookup(fuse_req_t req, fuse_ino_t parent, const char *name) @param ino The inode to git the attributes from. @param fi The file info (information about an open file). */ -void FuseRamFs::FuseGetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseGetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode = GetInode(ino); /* return enoent if this inode has been deleted */ @@ -486,7 +474,7 @@ void FuseRamFs::FuseGetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf fuse_reply_err(req, ENOENT); return; } - + inode->ReplyAttr(req); } @@ -500,8 +488,7 @@ void FuseRamFs::FuseGetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf @param to_set A mask of all incoming attributes that should be applied to the inode. @param fi The file info (information about an open file). */ -void FuseRamFs::FuseSetAttr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseSetAttr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode = GetInode(ino); /* return enoent if this inode has been deleted */ @@ -541,26 +528,25 @@ void FuseRamFs::FuseSetAttr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, i @param ino The directory inode. @param fi The file info (information about an open file). */ -void FuseRamFs::FuseOpenDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseOpenDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode = GetInode(ino); /* return enoent if this inode has been deleted */ if (inode == nullptr || inode->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; - } + } // You can't open a file with 'opendir'. Check for this. File *file = dynamic_cast(inode); if (file != nullptr) { fuse_reply_err(req, ENOTDIR); return; } - + // TODO: Handle permissions on files: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + fuse_reply_open(req, fi); } @@ -572,26 +558,25 @@ void FuseRamFs::FuseOpenDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf @param ino The directory inode. @param fi The file info (information about an open file). */ -void FuseRamFs::FuseReleaseDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseReleaseDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode = GetInode(ino); /* return enoent if this inode has been deleted */ if (inode == nullptr || inode->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; - } + } // You can't close a file with 'closedir'. Check for this. File *file = dynamic_cast(inode); if (file != nullptr) { fuse_reply_err(req, ENOTDIR); return; } - + // TODO: Handle permissions on files: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + fuse_reply_err(req, 0); } @@ -606,11 +591,10 @@ void FuseRamFs::FuseReleaseDir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_ @param fi The file info (information about an open file). */ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, - off_t off, struct fuse_file_info *fi) -{ + off_t off, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); (void) fi; - + Inode *inode = GetInode(ino); /* return ENOENT if this inode has been deleted */ if (inode == nullptr || inode->HasNoLinks()) { @@ -623,7 +607,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, fuse_reply_err(req, ENOTDIR); return; } - + Directory::ReadDirCtx *ctx; try { ctx = dir->PrepareReaddir(off); @@ -631,7 +615,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, fuse_reply_buf(req, nullptr, 0); return; } - + // Loop through and put children into a buffer until we have either: // a) exceeded the passed in size parameter, or // b) filled the maximum number of children per response, or @@ -646,10 +630,10 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, // added in the middle of our map of children while we were sending them. // This is why we access the children with an iterator (instead of using // some sort of index). - + struct stat stbuf{}; memset(&stbuf, 0, sizeof(stbuf)); - + // Pick the lesser of the max response size or our max size. size_t bufSize = FuseRamFs::kReadDirBufSize < size ? FuseRamFs::kReadDirBufSize : size; char *buf = (char *) malloc(bufSize); @@ -661,7 +645,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, // childIterator hasn't been newed up yet. size_t bytesAdded = 0; size_t entriesAdded = 0; - + while (entriesAdded < FuseRamFs::kReadDirEntriesPerResponse && ctx->it != ctx->children.end()) { fuse_ino_t child_ino = ctx->it->second; @@ -673,7 +657,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, childInode->GetAttr(&stbuf); stbuf.st_ino = ctx->it->second; - + // TODO: We don't look at sticky bits, etc. Revisit this in the future. // Inode &childInode = Inodes[stbuf.st_ino]; // Directory *childDir = dynamic_cast(&childInode); @@ -681,7 +665,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, // // This must be a file. // stbuf.st_mode // } - + size_t oldSize = bytesAdded; bytesAdded += fuse_add_direntry(req, buf + bytesAdded, @@ -704,8 +688,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, std::free(buf); } -void FuseRamFs::FuseOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode = GetInode(ino); /* return ENOENT if this inode has been deleted */ @@ -720,18 +703,17 @@ void FuseRamFs::FuseOpen(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info * fuse_reply_err(req, EISDIR); return; } - + // TODO: Handle permissions on files: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + // TODO: We seem to be able to delete a file and copy it back without a new inode being created. The only evidence is the open call. How do we handle this? fuse_reply_open(req, fi); } -void FuseRamFs::FuseRelease(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseRelease(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); /* return ENOENT if this inode has been deleted */ @@ -746,27 +728,25 @@ void FuseRamFs::FuseRelease(fuse_req_t req, fuse_ino_t ino, struct fuse_file_inf fuse_reply_err(req, EISDIR); return; } - + // TODO: Handle permissions on files: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + fuse_reply_err(req, 0); } -void FuseRamFs::FuseFsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseFsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); if (GetInode(ino) == nullptr) { fuse_reply_err(req, ENOENT); return; } - + fuse_reply_err(req, 0); } -void FuseRamFs::FuseFsyncDir(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseFsyncDir(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); @@ -774,20 +754,19 @@ void FuseRamFs::FuseFsyncDir(fuse_req_t req, fuse_ino_t ino, int datasync, struc fuse_reply_err(req, ENOENT); return; } - + // You can only sync a dir with 'fsyncdir'. Check for this. auto *dir_p = dynamic_cast(inode_p); if (dir_p == nullptr) { fuse_reply_err(req, ENOTDIR); return; } - + fuse_reply_err(req, 0); } void FuseRamFs::FuseMknod(fuse_req_t req, fuse_ino_t parent, const char *name, - mode_t mode, dev_t rdev) -{ + mode_t mode, dev_t rdev) { std::shared_lock lk(crMutex); Inode *parentInode = GetInode(parent); /* return ENOENT if this inode has been deleted */ @@ -814,15 +793,15 @@ void FuseRamFs::FuseMknod(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_reply_err(req, EEXIST); return; } - + // TODO: Handle permissions on dirs. You can't just create anything you please!: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - - const struct fuse_ctx* ctx_p = fuse_req_ctx(req); + + const struct fuse_ctx *ctx_p = fuse_req_ctx(req); long ino = do_create_node(parentDir_p, name, mode, rdev, ctx_p); - + if (ino > 0) { GetInode(ino)->ReplyEntry(req); } else { @@ -841,8 +820,8 @@ void FuseRamFs::FuseMknod(fuse_req_t req, fuse_ino_t parent, const char *name, * @return: If successful, return the inode number of created node. * Otherwise, return a negative error code. */ -long FuseRamFs::do_create_node(Directory *parent, const char *name, mode_t mode, dev_t dev, const struct fuse_ctx *ctx, const char *symlink) -{ +long FuseRamFs::do_create_node(Directory *parent, const char *name, mode_t mode, dev_t dev, const struct fuse_ctx *ctx, + const char *symlink) { Inode *new_node; nlink_t links = 1; @@ -908,11 +887,10 @@ long FuseRamFs::do_create_node(Directory *parent, const char *name, mode_t mode, return ino; } -void FuseRamFs::FuseMkdir(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode) -{ +void FuseRamFs::FuseMkdir(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode) { std::shared_lock lk(crMutex); Inode *parentInode = GetInode(parent); - + if (parentInode == nullptr || parentInode->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -935,15 +913,15 @@ void FuseRamFs::FuseMkdir(fuse_req_t req, fuse_ino_t parent, const char *name, m fuse_reply_err(req, EEXIST); return; } - + // TODO: Handle permissions on dirs. You can't just create anything you please!: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - - const struct fuse_ctx* ctx_p = fuse_req_ctx(req); + + const struct fuse_ctx *ctx_p = fuse_req_ctx(req); long ino = do_create_node(parentDir_p, name, mode | S_IFDIR, 0, ctx_p); - + if (ino > 0) { GetInode(ino)->ReplyEntry(req); } else { @@ -951,8 +929,7 @@ void FuseRamFs::FuseMkdir(fuse_req_t req, fuse_ino_t parent, const char *name, m } } -void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) -{ +void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) { std::shared_lock lk(crMutex); Inode *parentInode = GetInode(parent); /* return ENOENT if this inode has been deleted */ @@ -967,26 +944,26 @@ void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) fuse_reply_err(req, ENOTDIR); return; } - + // TODO: Handle permissions on dirs. You can't just delete anything you please!: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + // Return an error if the child doesn't exist. fuse_ino_t ino = parentDir_p->ChildInodeNumberWithName(string(name)); if (ino == INO_NOTFOUND) { fuse_reply_err(req, ENOENT); return; } - + // Point the name to the deleted block parentDir_p->RemoveChild(string(name)); - + Inode *inode_p = GetInode(ino); // TODO: Any way we can fail here? What if the inode doesn't exist? That probably indicates // a problem that happened earlier. assert(inode_p); - + // Update the number of hardlinks in the target inode_p->RemoveHardLink(); @@ -994,8 +971,7 @@ void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) fuse_reply_err(req, 0); } -void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) -{ +void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { std::shared_lock lk(crMutex); Inode *parentInode = GetInode(parent); /* return ENOENT if this inode has been deleted */ @@ -1010,18 +986,18 @@ void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) fuse_reply_err(req, ENOTDIR); return; } - + // TODO: Handle permissions on dirs. You can't just delete anything you please!: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + // Return an error if the child doesn't exist. fuse_ino_t ino = parentDir_p->ChildInodeNumberWithName(string(name)); if (ino == INO_NOTFOUND) { fuse_reply_err(req, ENOENT); return; } - + /* Prevent removing '.': raise error if ino == parent */ if (ino == parent) { fuse_reply_err(req, EINVAL); @@ -1050,37 +1026,34 @@ void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) fuse_reply_err(req, ENOTEMPTY); return; } - + parentDir_p->RemoveChild(name); // Update the number of hardlinks in the parent dir parentDir_p->RemoveHardLink(); - + // Remove the hard links to this dir so it can be cleaned up later // TODO: What if there's a real hardlink to this dir? Hardlinks to dirs allowed? // NOTE: No, hardlinks to dirs are not allowed. while (!dir_p->HasNoLinks()) { dir_p->RemoveHardLink(); } - + // Reply with no error. fuse_reply_err(req, 0); } -void FuseRamFs::FuseForget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) -{ +void FuseRamFs::FuseForget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr) { return; } inode_p->Forget(req, nlookup); - if (inode_p->Forgotten()) - { - if (inode_p->HasNoLinks()) - { + if (inode_p->Forgotten()) { + if (inode_p->HasNoLinks()) { // Let's just delete this inode and free memory. size_t blocks_freed = inode_p->UsedBlocks(); delete inode_p; @@ -1089,25 +1062,23 @@ void FuseRamFs::FuseForget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup DeleteInode(ino); FuseRamFs::UpdateUsedInodes(-1); FuseRamFs::UpdateUsedBlocks(-blocks_freed); - } - else - { + } else { // TODO: Verify that this only happens on unmount. It's OK on unmount but bad elsewhere. } } - + // Note that there's no reply here. That was done in the steps above this check. } -void FuseRamFs::FuseWrite(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseWrite(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, + struct fuse_file_info *fi) { std::shared_lock lk(crMutex); // TODO: Fuse seems to have problems writing with a null (buf) buffer. if (buf == nullptr) { fuse_reply_err(req, EINVAL); return; } - + Inode *inode_p = GetInode(ino); if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); @@ -1118,36 +1089,34 @@ void FuseRamFs::FuseWrite(fuse_req_t req, fuse_ino_t ino, const char *buf, size_ inode_p->WriteAndReply(req, buf, size, off); } -void FuseRamFs::FuseFlush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseFlush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { // TODO: Handle info in fi. - + fuse_reply_err(req, 0); } -void FuseRamFs::FuseRead(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) -{ +void FuseRamFs::FuseRead(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; } // TODO: Handle info in fi. - + inode_p->ReadAndReply(req, size, off); } -void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname) -{ +void +FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname) { std::shared_lock lk(crMutex); // Make sure the parents still exists. Inode *parentInode = GetInode(parent); Inode *newParentInode = GetInode(newparent); - + // Make sure it's not an already deleted inode if (parentInode == nullptr || parentInode->HasNoLinks()) { fuse_reply_err(req, ENOENT); @@ -1175,11 +1144,11 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, std::unique_lock G(FuseRamFs::renameMutex, std::defer_lock); std::unique_lock L1(parentDir->DirLock(), std::defer_lock); std::unique_lock L2(newParentDir->DirLock(), std::defer_lock); - + // TODO: Handle permissions on dirs. You can't just rename anything you please!: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + // Return an error if the source doesn't exist. fuse_ino_t srcIno = parentDir->ChildInodeNumberWithName(string(name)); Inode *srcInode = GetInode(srcIno); @@ -1187,7 +1156,7 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_reply_err(req, ENOENT); return; } - + /* Lock directories */ if (S_ISDIR(srcInode->GetMode())) { if (parent == newparent) { @@ -1237,11 +1206,15 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, return; } + //fuse_reply_err(req, ENOENT); + //return; /* Otherwise, let's replace the existing dest */ newParentDir->_UpdateChild(string(newname), srcIno); parentDir->_RemoveChild(string(name)); - existingInode->RemoveHardLink(); + //fuse_reply_err(req, ENOENT); + //return; if (S_ISDIR(existingInode->GetMode())) { + existingInode->RemoveHardLink(); /* An empty dir has two hard links * so we need to decrement one more time */ existingInode->RemoveHardLink(); @@ -1265,13 +1238,12 @@ void FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, } } -void FuseRamFs::FuseLink(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) -{ +void FuseRamFs::FuseLink(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) { std::shared_lock lk(crMutex); // Make sure the source inode and the parent exists. Inode *parent = GetInode(newparent); Inode *src = GetInode(ino); - + if (src == nullptr || src->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1298,25 +1270,24 @@ void FuseRamFs::FuseLink(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, c fuse_reply_err(req, EEXIST); return; } - + // Create the new name and point it to the inode. int ret = parentDir->AddChild(string(newname), ino); if (ret < 0) { fuse_reply_err(req, -ret); return; } - + // Update the number of hardlinks in the target src->AddHardLink(); - + parent->ReplyEntry(req); } -void FuseRamFs::FuseSymlink(fuse_req_t req, const char *link, fuse_ino_t parent, const char *name) -{ +void FuseRamFs::FuseSymlink(fuse_req_t req, const char *link, fuse_ino_t parent, const char *name) { std::shared_lock lk(crMutex); Inode *parent_p = GetInode(parent); - + if (parent_p == nullptr || parent_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1342,12 +1313,12 @@ void FuseRamFs::FuseSymlink(fuse_req_t req, const char *link, fuse_ino_t parent, fuse_reply_err(req, EEXIST); return; } - + // TODO: Handle permissions on dirs. You can't just make symlinks anywhere: // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - - const struct fuse_ctx* ctx_p = fuse_req_ctx(req); + + const struct fuse_ctx *ctx_p = fuse_req_ctx(req); long ino = do_create_node(dir, name, 0777 | S_IFLNK, 0, ctx_p, link); @@ -1356,14 +1327,13 @@ void FuseRamFs::FuseSymlink(fuse_req_t req, const char *link, fuse_ino_t parent, } else { fuse_reply_err(req, -ino); } - + } -void FuseRamFs::FuseReadLink(fuse_req_t req, fuse_ino_t ino) -{ +void FuseRamFs::FuseReadLink(fuse_req_t req, fuse_ino_t ino) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1375,18 +1345,17 @@ void FuseRamFs::FuseReadLink(fuse_req_t req, fuse_ino_t ino) fuse_reply_err(req, EINVAL); return; } - + // TODO: Handle permissions. // else if ((fi->flags & 3) != O_RDONLY) // fuse_reply_err(req, EACCES); - + //const struct fuse_ctx* ctx_p = fuse_req_ctx(req); - + fuse_reply_readlink(req, link_p->Link().c_str()); } -void FuseRamFs::FuseStatfs(fuse_req_t req, fuse_ino_t ino) -{ +void FuseRamFs::FuseStatfs(fuse_req_t req, fuse_ino_t ino) { std::shared_lock lk(crMutex); struct statvfs info{}; FuseRamFs::FsStat(&info); @@ -1396,12 +1365,14 @@ void FuseRamFs::FuseStatfs(fuse_req_t req, fuse_ino_t ino) #ifdef __APPLE__ void FuseRamFs::FuseSetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags, uint32_t position) #else -void FuseRamFs::FuseSetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags) + +void +FuseRamFs::FuseSetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags) #endif { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1417,12 +1388,13 @@ void FuseRamFs::FuseSetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, c #ifdef __APPLE__ void FuseRamFs::FuseGetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size, uint32_t position) #else + void FuseRamFs::FuseGetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) #endif { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1431,12 +1403,11 @@ void FuseRamFs::FuseGetXAttr(fuse_req_t req, fuse_ino_t ino, const char *name, s #ifndef __APPLE__ uint32_t position = 0; #endif - + inode_p->GetXAttrAndReply(req, string(name), size, position); } -void FuseRamFs::FuseListXAttr(fuse_req_t req, fuse_ino_t ino, size_t size) -{ +void FuseRamFs::FuseListXAttr(fuse_req_t req, fuse_ino_t ino, size_t size) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); @@ -1448,11 +1419,10 @@ void FuseRamFs::FuseListXAttr(fuse_req_t req, fuse_ino_t ino, size_t size) inode_p->ListXAttrAndReply(req, size); } -void FuseRamFs::FuseRemoveXAttr(fuse_req_t req, fuse_ino_t ino, const char *name) -{ +void FuseRamFs::FuseRemoveXAttr(fuse_req_t req, fuse_ino_t ino, const char *name) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; @@ -1460,22 +1430,21 @@ void FuseRamFs::FuseRemoveXAttr(fuse_req_t req, fuse_ino_t ino, const char *name inode_p->RemoveXAttrAndReply(req, string(name)); } -void FuseRamFs::FuseAccess(fuse_req_t req, fuse_ino_t ino, int mask) -{ +void FuseRamFs::FuseAccess(fuse_req_t req, fuse_ino_t ino, int mask) { std::shared_lock lk(crMutex); Inode *inode_p = GetInode(ino); - + if (inode_p == nullptr || inode_p->HasNoLinks()) { fuse_reply_err(req, ENOENT); return; } - const struct fuse_ctx* ctx_p = fuse_req_ctx(req); - + const struct fuse_ctx *ctx_p = fuse_req_ctx(req); + inode_p->ReplyAccess(req, mask, ctx_p->gid, ctx_p->uid); } -void FuseRamFs::FuseCreate(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info *fi) -{ +void +FuseRamFs::FuseCreate(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info *fi) { std::shared_lock lk(crMutex); Inode *parent_p = GetInode(parent); if (parent_p == nullptr || parent_p->HasNoLinks()) { @@ -1488,9 +1457,9 @@ void FuseRamFs::FuseCreate(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_reply_err(req, ENOTDIR); return; } - - const struct fuse_ctx* ctx_p = fuse_req_ctx(req); - + + const struct fuse_ctx *ctx_p = fuse_req_ctx(req); + long ino = do_create_node(parentDir_p, name, mode | S_IFREG, 0, ctx_p); if (ino > 0) { FuseRamFs::GetInode(ino)->ReplyCreate(req, fi); @@ -1499,14 +1468,12 @@ void FuseRamFs::FuseCreate(fuse_req_t req, fuse_ino_t parent, const char *name, } } -void FuseRamFs::FuseGetLock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock) -{ +void FuseRamFs::FuseGetLock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock) { // TODO: implement locking (Custom lock impl is only needed for distributed file systems) //inode_p->ReplyGetLock(req, lock); } -fuse_ino_t FuseRamFs::RegisterInode(Inode *inode_p, mode_t mode, nlink_t nlink, gid_t gid, uid_t uid) -{ +fuse_ino_t FuseRamFs::RegisterInode(Inode *inode_p, mode_t mode, nlink_t nlink, gid_t gid, uid_t uid) { // Either re-use a deleted inode or push one back depending on whether we're reclaiming inodes now or // not. fuse_ino_t ino; diff --git a/src/inode.cpp b/src/inode.cpp index 744c378..d307228 100644 --- a/src/inode.cpp +++ b/src/inode.cpp @@ -365,6 +365,8 @@ size_t Inode::Load(const void *&buf) { size_t n_xattrs; memcpy(&n_xattrs, ptr, sizeof(n_xattrs)); ptr += sizeof(n_xattrs); + + m_xattr.clear(); // load xattrs for (size_t i = 0; i < n_xattrs; ++i) { // key diff --git a/src/pickle.cpp b/src/pickle.cpp index 97580fd..e51b620 100644 --- a/src/pickle.cpp +++ b/src/pickle.cpp @@ -122,20 +122,41 @@ int pickle_file_system(int fd, std::vector &inodes, pending_delete_inodes.push(ino); } - /*size_t num_state_pool = state_pool.size(); + // start pickling checkpoint/restore pools + auto state_pool = get_state_pool(); + + size_t num_state_pool = state_pool.size(); write_and_hash(fd, hashctx, &num_state_pool, sizeof(num_state_pool)); for (const auto &state: state_pool) { - uint64_t key=state.first; + uint64_t key = state.first; write_and_hash(fd, hashctx, &key, sizeof(key)); std::tuple - , std::queue, - struct statvfs> stored_states=state.second; - std::vector stored_files = std::get<0>(stored_states); + , std::queue, + struct statvfs> stored_states = state.second; + std::vector stored_files = std::get<0>(stored_states); size_t num_stored_files = stored_files.size(); write_and_hash(fd, hashctx, &num_stored_files, sizeof(num_stored_files)); - for(const auto &stored_file:stored_files){ - write_and_hash(fd, hashctx, &stored_file, sizeof(stored_file)); + for (const auto &inode:stored_files) { + struct inode_state iinfo = {}; + if (inode == nullptr) { + iinfo.exist = false; + write_and_hash(fd, hashctx, &iinfo, sizeof(iinfo)); + continue; + } + size_t pickled_size = inode->GetPickledSize(); + void *data = malloc(pickled_size); + if (data == nullptr) { + throw pickle_error(ENOMEM, __func__, __LINE__); + } + /* Should not fail, because the buffer is preallocated */ + inode->Pickle(data); + iinfo.mode = inode->GetMode(); + iinfo.exist = true; + write_and_hash(fd, hashctx, &iinfo, sizeof(iinfo)); + write_and_hash(fd, hashctx, data, pickled_size); + + free(data); } std::queue stored_DeletedInodes = std::get<1>(stored_states); @@ -151,7 +172,7 @@ int pickle_file_system(int fd, std::vector &inodes, struct statvfs stored_m_stbuf = std::get<2>(stored_states); write_and_hash(fd, hashctx, &stored_m_stbuf, sizeof(stored_m_stbuf)); - }*/ + } } catch (const pickle_error &e) { lseek(fd, fpos, SEEK_SET); @@ -359,6 +380,84 @@ ssize_t load_file_system(const void *data, std::vector &inodes, ptr += sizeof(ino); } + // start unpickling checkpoint/restore pools + auto state_pool = get_state_pool(); + + state_pool.clear(); + size_t num_state_pool; + memcpy(&num_state_pool, ptr, sizeof(num_state_pool)); + ptr += sizeof(num_state_pool); + + for (size_t i = 0; i < num_state_pool; ++i) { + uint64_t key; + memcpy(&key, ptr, sizeof(key)); + ptr += sizeof(key); + + size_t num_stored_files; + memcpy(&num_stored_files, ptr, sizeof(num_stored_files)); + ptr += sizeof(num_stored_files); + + auto cr_inodes = std::vector(); + + for (size_t j = 0; j < num_stored_files; ++j) { + struct inode_state iinfo; + memcpy(&iinfo, ptr, sizeof(iinfo)); + ptr += sizeof(iinfo); + if (!iinfo.exist) + continue; + + size_t res; + const void *ptr2 = (const void *) ptr; + if (S_ISREG(iinfo.mode)) { + File *file = new File(); + res = file->Load(ptr2); + cr_inodes.push_back(file); + } else if (S_ISDIR(iinfo.mode)) { + auto *dir = new Directory(); + res = dir->Load(ptr2); + cr_inodes.push_back(dir); + } else if (S_ISLNK(iinfo.mode)) { + auto *link = new SymLink(); + res = link->Load(ptr2); + cr_inodes.push_back(link); + } else if (S_ISCHR(iinfo.mode) || S_ISBLK(iinfo.mode) || + S_ISSOCK(iinfo.mode) || S_ISFIFO(iinfo.mode) || iinfo.mode == 0) { + auto *special = new SpecialInode(); + res = special->Load(ptr2); + cr_inodes.push_back(special); + } else { + throw pickle_error(EINVAL, __func__, __LINE__); + } + + if (res == 0) { + throw pickle_error(ENOMEM, __func__, __LINE__); + } + ptr += res; + } + + auto cr_deleted_inodes = std::queue(); + size_t num_stored_DeletedInodes; + memcpy(&num_stored_DeletedInodes, ptr, sizeof(num_stored_DeletedInodes)); + ptr += sizeof(num_stored_DeletedInodes); + + for (size_t j = 0; j < num_stored_DeletedInodes; ++j) { + fuse_ino_t ino; + memcpy(&ino, ptr, sizeof(ino)); + ptr += sizeof(ino); + cr_deleted_inodes.push(ino); + } + + struct statvfs stored_m_stbuf; + memcpy(&stored_m_stbuf, ptr, sizeof(stored_m_stbuf)); + ptr += sizeof(stored_m_stbuf); + + int ret; + ret = insert_state(key, std::make_tuple(cr_inodes, cr_deleted_inodes, stored_m_stbuf)); + if (ret != 0) { + throw pickle_error(EINVAL, __func__, __LINE__); + } + } + } catch (const pickle_error &e) { return -e.get_errno(); } @@ -404,6 +503,7 @@ int FuseRamFs::load_verifs2(void) { if (mapped == MAP_FAILED) throw pickle_error(errno, __func__, __LINE__); // load the file system + clear_states(); FuseRamFs::Inodes.clear(); while (!FuseRamFs::DeletedInodes.empty()) FuseRamFs::DeletedInodes.pop(); diff --git a/tests/pkl_load_test.py b/tests/pkl_load_test.py deleted file mode 100755 index 3c87d55..0000000 --- a/tests/pkl_load_test.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python3 -import glob -import subprocess -import os -import sys -import time -import errno -import random -import signal -import psutil -from contextlib import suppress - -# config -fs_exec = 'fuse-cpp-ramfs' # bin program or path, ex: ../../verifs1/crmfs -path_to_fs = '{}/mnt/fuse-cpp-ramfs'.format(os.getcwd()) # absolute path only -absfs_path = '../../fs-state/absfs' -pkl_path = '../build/pkl' -load_path = '../build/load' -'''*You need to comment out (rm -rf "$DIR") in racer script for this to work correctly''' -racer_script_path = 'racer/racer.sh' -'''range format: [a,b)''' -racer_duration = (1, 5) -racer_threads = (3, 7) -num_test_attempts = (5, 10) -# - -print(sys.platform) - -config_list = [] -size = 0 -success_count = 0 -p = None -child = None -random_num_attempts = random.randrange(num_test_attempts[0], num_test_attempts[1]) - - -def get_random_in_range(range_tpl): - return random.randrange(range_tpl[0], range_tpl[1]) - - -def make_sure_path_exists(path): - try: - os.makedirs(path) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - - -def get_fs_signature(): - p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) - raw_res = p1.communicate()[0] - signature = raw_res.rsplit(b' ', 1)[1] - while signature == b'iterating...\n': - if b'cannot stat' in raw_res: - print('encountered false-positive while calculating the signature, retrying in 5 sec...') - time.sleep(5) - p1 = subprocess.Popen([absfs_path, path_to_fs], stdout=subprocess.PIPE) - raw_res = p1.communicate()[0] - signature = raw_res.rsplit(b' ', 1)[1] - continue - else: - raise Exception(raw_res) - return signature - - -def pickle_save_signature(): - global size - signature = get_fs_signature() - config_list.append(signature) - subprocess.run([pkl_path, path_to_fs, 'pickle_tmp{}'.format(size)]) - print('saved pickle file at index {}, signature: {}'.format(size, signature)) - size += 1 - - -def load_verify_signature(i): - global success_count - - subprocess.run([load_path, path_to_fs, 'pickle_tmp{}'.format(i)]) - signature = config_list[i] - time.sleep(3) - new_signature = get_fs_signature() - if new_signature == signature: - print('loaded pickle file at index {} passed verification, signature: {}'.format(i, signature)) - success_count += 1 - else: - print('signature at index {} has a discrepancy: {} -> {}'.format(i, signature, new_signature)) - - -def clean_files(prefix, cwd=None): - if prefix == '/' or (prefix == '' and cwd is None): - raise Exception('dangerous action') - subprocess.run(['rm', '-rf', '{}*'.format(prefix)], cwd=cwd) - - -def run(cmd, cwd=path_to_fs): - subprocess.run(cmd, cwd=cwd) - - -def unmount(): - time.sleep(1) - # If you unmount too soon, the mountpoint won't be available. - if sys.platform == 'darwin' or sys.platform == 'linux': - subprocess.run(['umount', - path_to_fs]) - else: - subprocess.run(['fusermount', '-u', - path_to_fs]) - - -def clean_exit(): - unmount() - - print('perform cleanup......') - - for fl in glob.glob('pickle_tmp*'): - os.remove(fl) - - -def wait_for_process(name): - while name in (i.name() for i in psutil.process_iter()): - print('waiting for {} to terminate......'.format(name)) - time.sleep(5) - time.sleep(1) - - -# =================================================== - - -def perform_test(): - global p, child, random_num_attempts - for i in range(random_num_attempts): - child = subprocess.Popen([fs_exec, - path_to_fs]) - time.sleep(1) - - wait_for_process("dd") - - p = subprocess.Popen([racer_script_path, - path_to_fs, - str(get_random_in_range(racer_duration)), - str(get_random_in_range(racer_threads))]) - - p.wait() - - wait_for_process("dd") - - pickle_save_signature() - - wait_for_process("dd") - - p = subprocess.Popen([racer_script_path, - path_to_fs, - str(get_random_in_range(racer_duration)), - str(get_random_in_range(racer_threads))]) - - p.wait() - - wait_for_process("dd") - - load_verify_signature(size - 1) - - time.sleep(1) - unmount() - - -# =================================================== - -make_sure_path_exists(path_to_fs) - -clean_files('', path_to_fs) - -try: - perform_test() - print("Test Complete,Success: {}/{}\n-----------------------------".format(success_count, random_num_attempts)) -except KeyboardInterrupt: - pass -except Exception as err: - print(err) - if p is not None: - pid = p.pid - with suppress(Exception): - os.kill(pid, signal.SIGINT) # or SIGINT to CTRL_C_EVENT for Windows - input() - pass - -clean_exit() - -child.wait() -sys.exit(child.returncode) From 9ac14083dd1c09d20b9fbcf7d3021897c900992c Mon Sep 17 00:00:00 2001 From: peiliou Date: Sun, 29 Aug 2021 20:42:33 -0400 Subject: [PATCH 09/18] rename link count functions --- src/fuse_cpp_ramfs.cpp | 20 ++++++++++---------- src/inode.hpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/fuse_cpp_ramfs.cpp b/src/fuse_cpp_ramfs.cpp index 26c2893..2c10803 100644 --- a/src/fuse_cpp_ramfs.cpp +++ b/src/fuse_cpp_ramfs.cpp @@ -882,7 +882,7 @@ long FuseRamFs::do_create_node(Directory *parent, const char *name, mode_t mode, } /* Only add hard link to the parent dir if everything above succeeded */ if (S_ISDIR(mode)) { - parent->AddHardLink(); + parent->IncrementLinkCount(); } return ino; } @@ -965,7 +965,7 @@ void FuseRamFs::FuseUnlink(fuse_req_t req, fuse_ino_t parent, const char *name) assert(inode_p); // Update the number of hardlinks in the target - inode_p->RemoveHardLink(); + inode_p->DecrementLinkCount(); // Reply with no error. TODO: Where is ESUCCESS? fuse_reply_err(req, 0); @@ -1029,13 +1029,13 @@ void FuseRamFs::FuseRmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { parentDir_p->RemoveChild(name); // Update the number of hardlinks in the parent dir - parentDir_p->RemoveHardLink(); + parentDir_p->DecrementLinkCount(); // Remove the hard links to this dir so it can be cleaned up later // TODO: What if there's a real hardlink to this dir? Hardlinks to dirs allowed? // NOTE: No, hardlinks to dirs are not allowed. while (!dir_p->HasNoLinks()) { - dir_p->RemoveHardLink(); + dir_p->DecrementLinkCount(); } // Reply with no error. @@ -1214,13 +1214,13 @@ FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ //fuse_reply_err(req, ENOENT); //return; if (S_ISDIR(existingInode->GetMode())) { - existingInode->RemoveHardLink(); + existingInode->DecrementLinkCount(); /* An empty dir has two hard links * so we need to decrement one more time */ - existingInode->RemoveHardLink(); + existingInode->DecrementLinkCount(); /* Decrement one link for the old parent because the source * dir has been moved out */ - parentDir->RemoveHardLink(); + parentDir->DecrementLinkCount(); } fuse_reply_err(req, 0); } else { @@ -1230,9 +1230,9 @@ FuseRamFs::FuseRename(fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ if (S_ISDIR(srcInode->GetMode())) { /* Decrement one link for the old parent because the source * dir has been moved out */ - parentDir->RemoveHardLink(); + parentDir->DecrementLinkCount(); /* Increment one link for the new parent because of moving in */ - newParentDir->AddHardLink(); + newParentDir->IncrementLinkCount(); } fuse_reply_err(req, 0); } @@ -1279,7 +1279,7 @@ void FuseRamFs::FuseLink(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, c } // Update the number of hardlinks in the target - src->AddHardLink(); + src->IncrementLinkCount(); parent->ReplyEntry(req); } diff --git a/src/inode.hpp b/src/inode.hpp index b677d84..68bd0be 100644 --- a/src/inode.hpp +++ b/src/inode.hpp @@ -60,11 +60,11 @@ class Inode { virtual int ReplyAccess(fuse_req_t req, int mask, gid_t gid, uid_t uid); /* Atomic file attribute operations */ - void AddHardLink() { + void IncrementLinkCount() { std::unique_lock lk(entryRwSem); m_fuseEntryParam.attr.st_nlink++; } - void RemoveHardLink() { + void DecrementLinkCount() { std::unique_lock lk(entryRwSem); m_fuseEntryParam.attr.st_nlink--; } From f2f9405e2bca2251e803ec9ed8e8ff881c7e376e Mon Sep 17 00:00:00 2001 From: Wei Su Date: Fri, 26 Nov 2021 22:40:31 -0500 Subject: [PATCH 10/18] Revise the logic of readdir to make sure each dirent has a unique cookie, and recycle expired readdir contexts --- src/directory.cpp | 39 ++++++++++++++++++++++++++------------- src/directory.hpp | 1 + src/fuse_cpp_ramfs.cpp | 3 ++- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/directory.cpp b/src/directory.cpp index 3087fe4..3cc784d 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -146,18 +146,16 @@ int Directory::ReadAndReply(fuse_req_t req, size_t size, off_t off) { return fuse_reply_err(req, EISDIR); } +/* The cookie uses 32 bits, with the higher 16 bit the key to the readdir + * context, and the lower 16 bit representing the index of the directory entry. + */ Directory::ReadDirCtx* Directory::PrepareReaddir(off_t cookie) { + off_t key = 0; if (cookie != 0) { /* NOTE: Will throw std::out_of_range if no entry is found */ - Directory::ReadDirCtx* ctx = readdirStates.at(cookie); - - /* If we have reached the end of the iterator, we should destroy this context - * to release memory */ - if (ctx->it == ctx->children.end()) { - Directory::readdirStates.erase(cookie); - delete ctx; - throw(std::out_of_range("Not found")); - } + key = (cookie & 0xffff0000) >> 16; + Directory::ReadDirCtx* ctx = readdirStates.at(key); + return ctx; } /* Make a copy of children */ @@ -166,16 +164,31 @@ Directory::ReadDirCtx* Directory::PrepareReaddir(off_t cookie) { lk.unlock(); /* Add it to the table */ - cookie = rand(); + key = rand() & 0xffff; /* Make sure there is no duplicate */ - while (readdirStates.find(cookie) != readdirStates.end()) { - cookie = rand(); + while (readdirStates.find(key) != readdirStates.end()) { + key = rand() & 0xffff; } + cookie = 0; + cookie = key << 16; ReadDirCtx *newctx = new ReadDirCtx(cookie, copiedChildren); - readdirStates.insert({cookie, newctx}); + readdirStates.insert({key, newctx}); return newctx; } +void Directory::RecycleStates() { + // find context objects whose iterators have reached the end, and free them + for (auto ctxiter = readdirStates.begin(); ctxiter != readdirStates.end();) { + Directory::ReadDirCtx *ctx = ctxiter->second; + if (ctx->it == ctx->children.end()) { + delete ctx; + ctxiter = readdirStates.erase(ctxiter); + } else { + ++ctxiter; + } + } +} + bool Directory::IsEmpty() { std::shared_lock lk(childrenRwSem); for (auto it = m_children.begin(); it != m_children.end(); ++it) { diff --git a/src/directory.hpp b/src/directory.hpp index 7987afc..4916551 100644 --- a/src/directory.hpp +++ b/src/directory.hpp @@ -28,6 +28,7 @@ class Directory : public Inode { static std::unordered_map readdirStates; ReadDirCtx* PrepareReaddir(off_t cookie); + void RecycleStates(); friend class FuseRamFs; public: ~Directory() {} diff --git a/src/fuse_cpp_ramfs.cpp b/src/fuse_cpp_ramfs.cpp index eba3f76..27352d7 100644 --- a/src/fuse_cpp_ramfs.cpp +++ b/src/fuse_cpp_ramfs.cpp @@ -682,7 +682,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, bufSize - bytesAdded, ctx->it->first.c_str(), &stbuf, - ctx->cookie); + ++ctx->cookie); if (bytesAdded > bufSize) { // Oops. There wasn't enough space for that last item. Back up and exit. --(ctx->it); @@ -694,6 +694,7 @@ void FuseRamFs::FuseReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, } } + dir->RecycleStates(); fuse_reply_buf(req, buf, bytesAdded); std::free(buf); } From daf471446109bd8b2debf555e317caa57f3b79d0 Mon Sep 17 00:00:00 2001 From: Wei Su Date: Mon, 20 Dec 2021 21:30:12 -0500 Subject: [PATCH 11/18] We don't need PDF docs on server --- doc/english/CMakeLists.txt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/english/CMakeLists.txt b/doc/english/CMakeLists.txt index 522a2da..4b50db7 100644 --- a/doc/english/CMakeLists.txt +++ b/doc/english/CMakeLists.txt @@ -5,7 +5,7 @@ add_custom_command(OUTPUT fuse-cpp-ramfs.ps add_custom_target(postscript ALL DEPENDS fuse-cpp-ramfs.ps) -# Set GROFF_NO_SGR because the following txt rule running ul is incompatible with the +# Set GROFF_NO_SGR because the following txt rule running ul is incompatible with the # default. add_custom_command(OUTPUT fuse-cpp-ramfs.1 COMMAND export GROFF_NO_SGR=1 && groff -e -T ascii -man ${CMAKE_CURRENT_SOURCE_DIR}/fuse-cpp-ramfs.man > fuse-cpp-ramfs.1 @@ -21,14 +21,6 @@ add_custom_command(OUTPUT fuse-cpp-ramfs.txt add_custom_target(txt ALL DEPENDS fuse-cpp-ramfs.txt) -add_custom_command(OUTPUT fuse-cpp-ramfs.pdf - COMMAND ps2pdf fuse-cpp-ramfs.ps > fuse-cpp-ramfs.pdf - DEPENDS fuse-cpp-ramfs.ps - COMMENT "Creating pdf file") -add_custom_target(pdf ALL - DEPENDS fuse-cpp-ramfs.pdf) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fuse-cpp-ramfs.ps" DESTINATION "${DOCDIR}") install(FILES fuse-cpp-ramfs.man DESTINATION "${MANDIR}/man1" RENAME fuse-cpp-ramfs.1) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fuse-cpp-ramfs.txt" DESTINATION "${DOCDIR}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fuse-cpp-ramfs.pdf" DESTINATION "${DOCDIR}") \ No newline at end of file From cb61eea9ca33b6321decfb3c20d57615502c6a52 Mon Sep 17 00:00:00 2001 From: Wei Su Date: Mon, 20 Dec 2021 21:31:07 -0500 Subject: [PATCH 12/18] Create and install the mount helper when building the project, so that we can mount verifs2 using the mount command --- src/CMakeLists.txt | 9 ++++++++ src/create-mount-helper.sh | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100755 src/create-mount-helper.sh diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f4425c2..e1d360c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,4 +24,13 @@ endif() target_link_libraries(fuse-cpp-ramfs pthread) target_link_libraries(ckpt pthread) target_link_libraries(restore pthread) +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/mount.fuse.fuse-cpp-ramfs + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/create-mount-helper.sh + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_custom_target( + mount-helper ALL + DEPENDS fuse-cpp-ramfs ${CMAKE_BINARY_DIR}/mount.fuse.fuse-cpp-ramfs) install(TARGETS fuse-cpp-ramfs DESTINATION bin) +install(PROGRAMS ${CMAKE_BINARY_DIR}/mount.fuse.fuse-cpp-ramfs DESTINATION /sbin) + diff --git a/src/create-mount-helper.sh b/src/create-mount-helper.sh new file mode 100755 index 0000000..9202d5d --- /dev/null +++ b/src/create-mount-helper.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +DEST_DIR=$(pwd) +DEST_NAME=mount.fuse.fuse-cpp-ramfs +DEST=$DEST_DIR/$DEST_NAME +FUSE_RAMFS_BINDIR=$(pwd) + +echo '#!/bin/bash' > $DEST +echo '' >> $DEST +echo 'if [ "$#" -lt 2 ]; then' >> $DEST +echo ' echo "Usage: $0 [-o options]";' >> $DEST +echo ' exit 1;' >> $DEST +echo 'fi' >> $DEST +echo '' >> $DEST +echo "FUSE_RAMFS_BINDIR=$FUSE_RAMFS_BINDIR" >> $DEST +echo 'MNT_NAME=$1' >> $DEST +echo 'MNT_DIR=$2' >> $DEST +echo 'OPTS=' >> $DEST +echo 'FUSE_CPP_RAMFS_PROG=$FUSE_RAMFS_BINDIR/src/fuse-cpp-ramfs' >> $DEST +echo 'FUSE_CPP_RAMFS_MOUNT=$FUSE_RAMFS_BINDIR/mnts' >> $DEST +echo '' >> $DEST +echo '# If there is options string?' >> $DEST +echo 'if [ "$#" -gt 2 ] && [ "$3" == "-o" ]; then' >> $DEST +echo ' OPTS=$4;' >> $DEST +echo 'fi' >> $DEST +echo '' >> $DEST +echo 'mkdir -p $FUSE_CPP_RAMFS_MOUNT' >> $DEST +echo 'ln -fs $FUSE_CPP_RAMFS_PROG $FUSE_CPP_RAMFS_MOUNT/$MNT_NAME' >> $DEST +echo '' >> $DEST +echo 'if [ -n "$OPTS" ]; then' >> $DEST +echo ' nohup $FUSE_CPP_RAMFS_MOUNT/$MNT_NAME -o $OPTS $MNT_DIR 2>&1 > $FUSE_CPP_RAMFS_MOUNT/$MNT_NAME.out &' >> $DEST +echo 'else' >> $DEST +echo ' nohup $FUSE_CPP_RAMFS_MOUNT/$MNT_NAME $MNT_DIR 2>&1 > $FUSE_CPP_RAMFS_MOUNT/$MNT_NAME.out &' >> $DEST +echo 'fi' >> $DEST +echo '' >> $DEST +echo 'if [ -z "$(pgrep $MNT_NAME)" ]; then' >> $DEST +echo ' echo "Mount failed.";' >> $DEST +echo ' exit 1;' >> $DEST +echo 'fi' >> $DEST +echo '' >> $DEST +echo 'exit 0;' >> $DEST + +chmod +x $DEST From 8ab0635b40a95e2b838075ed2a913507e260b797 Mon Sep 17 00:00:00 2001 From: Wei Su Date: Mon, 20 Dec 2021 21:34:22 -0500 Subject: [PATCH 13/18] Update doc --- README.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index ad300da..939f4bf 100644 --- a/README.rst +++ b/README.rst @@ -14,9 +14,10 @@ Quick Run cd build cmake ../src make - make install - - + sudo make install + sudo mkdir /mnt/test-verifs2 + sudo mount -t fuse.fuse-cpp-ramfs verifs2 /mnt/test-verifs2 + Requirements ============ fuse-cpp-ramfs builds with CMake version 3.0 or greater. From 235ada83bb237bde6267da70c78dfe153070e839 Mon Sep 17 00:00:00 2001 From: Yifei Liu Date: Sun, 16 Jan 2022 21:07:25 +0000 Subject: [PATCH 14/18] Remove unnecessary ckpt_restore_test.sh --- ckpt_restore_test.sh | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 ckpt_restore_test.sh diff --git a/ckpt_restore_test.sh b/ckpt_restore_test.sh deleted file mode 100644 index 6969182..0000000 --- a/ckpt_restore_test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -BUILDPATH=/home/yifei/zram_test/VeriFS2-ioctl-20210212/fuse-cpp-ramfs/build - -rm -rf $BUILDPATH/* -cd $BUILDPATH -cmake ../src -make -sudo make install -sudo umount -l /mnt/test-verifs2 -sudo rm -rf /mnt/test-verifs2/* -sudo umount -l /mnt/test-verifs1 -sudo rm -rf /mnt/test-verifs1/* -sudo rm -r /mnt/test-verifs2 -sudo rm -r /mnt/test-verifs1 -sudo mkdir /mnt/test-verifs2 -sudo mkdir /mnt/test-verifs1 -sudo chown yifei:yifei /mnt/test-verifs2 -sudo chown yifei:yifei /mnt/test-verifs1 - From 6c498768f470b89689776ee07f76615317788a64 Mon Sep 17 00:00:00 2001 From: Yifei Liu Date: Fri, 4 Feb 2022 20:47:57 -0500 Subject: [PATCH 15/18] Fix a tiny issue in create mount script --- src/create-mount-helper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/create-mount-helper.sh b/src/create-mount-helper.sh index 9202d5d..ba54ffe 100755 --- a/src/create-mount-helper.sh +++ b/src/create-mount-helper.sh @@ -16,7 +16,7 @@ echo "FUSE_RAMFS_BINDIR=$FUSE_RAMFS_BINDIR" >> $DEST echo 'MNT_NAME=$1' >> $DEST echo 'MNT_DIR=$2' >> $DEST echo 'OPTS=' >> $DEST -echo 'FUSE_CPP_RAMFS_PROG=$FUSE_RAMFS_BINDIR/src/fuse-cpp-ramfs' >> $DEST +echo 'FUSE_CPP_RAMFS_PROG=$FUSE_RAMFS_BINDIR/fuse-cpp-ramfs' >> $DEST echo 'FUSE_CPP_RAMFS_MOUNT=$FUSE_RAMFS_BINDIR/mnts' >> $DEST echo '' >> $DEST echo '# If there is options string?' >> $DEST From ef58c0ec524e39c13bdbc9d897a70d34a932c6f9 Mon Sep 17 00:00:00 2001 From: Yifei Liu Date: Mon, 21 Feb 2022 13:57:37 -0500 Subject: [PATCH 16/18] Update README --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 939f4bf..8d00424 100644 --- a/README.rst +++ b/README.rst @@ -11,6 +11,7 @@ Quick Run ========= :: + mkdir build cd build cmake ../src make From 6ee7d0704141849bfc643c639ce09f52b6701fb7 Mon Sep 17 00:00:00 2001 From: Yifei Liu Date: Sat, 26 Feb 2022 23:04:34 -0500 Subject: [PATCH 17/18] script to build and mount verifs2 --- build_verifs2.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 build_verifs2.sh diff --git a/build_verifs2.sh b/build_verifs2.sh new file mode 100755 index 0000000..de34087 --- /dev/null +++ b/build_verifs2.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +fsname="verifs2" +BUILD_DIR="build" +MOUNT_POINT="/mnt/test-$fsname" + +if [ -d ./$BUILD_DIR ]; then + rm -r ./$BUILD_DIR +fi + +mkdir -p ./$BUILD_DIR + +cd ./$BUILD_DIR +cmake ../src +make +sudo make install + +if [ "$(mount | grep $MOUNT_POINT)" ]; then + sudo umount -f $MOUNT_POINT; +fi + +if [ -d $MOUNT_POINT ]; then + sudo rm -rf $MOUNT_POINT; +fi + +sudo mkdir $MOUNT_POINT +sudo mount -t fuse.fuse-cpp-ramfs $fsname $MOUNT_POINT From 40d32da3383dd30877bb62ea7e2b2f9851d610c7 Mon Sep 17 00:00:00 2001 From: Pei Liu Date: Thu, 12 May 2022 21:11:12 -0400 Subject: [PATCH 18/18] fix all verifs2 init/exit valgrind issues --- src/main.cpp | 11 ++++++----- src/util.cpp | 7 ++++--- tests/compile.sh | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 34bc746..91db4fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,10 +10,10 @@ using namespace std; char **copy_args(int argc, const char * argv[]) { - char **new_argv = new char*[argc]; + char **new_argv = (char **)malloc(sizeof(char *)*argc); for (int i = 0; i < argc; ++i) { int len = (int) strlen(argv[i]) + 1; - new_argv[i] = new char[len]; + new_argv[i] = (char *)malloc(len); strncpy(new_argv[i], argv[i], len); } return new_argv; @@ -21,9 +21,9 @@ char **copy_args(int argc, const char * argv[]) { void delete_args(int argc, char **argv) { for (int i = 0; i < argc; ++i) { - delete argv[i]; + delete[] argv[i]; } - delete argv; + delete[] argv; } struct fuse_chan *ch; @@ -68,11 +68,12 @@ int main(int argc, const char * argv[]) { fuse_session_destroy(se); } fuse_unmount(mountpoint, ch); + delete[] mountpoint; } } fuse_opt_free_args(&args); - delete_args(argc, fuse_argv); + //delete_args(argc, fuse_argv); return err ? 1 : 0; } diff --git a/src/util.cpp b/src/util.cpp index 3e29dd0..a8e3aef 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -171,6 +171,7 @@ void ramfs_set_subtype(struct fuse_args *args, const char *subtype) { } snprintf(subtype_str, len, "-osubtype=%s", subtype); fuse_opt_add_arg(args, subtype_str); + delete[] subtype_str; } void erase_arg(struct fuse_args &args, int index) { @@ -185,7 +186,7 @@ void erase_arg(struct fuse_args &args, int index) { args.argv[args.argc - 1] = nullptr; args.argc--; if (args.allocated) { - delete target; + free(target); } } /* ramfs_parse_cmdline: Parse command line arguments @@ -213,7 +214,7 @@ void ramfs_parse_cmdline(struct fuse_args &args, struct fuse_ramfs_options &opti optstr_buf = new char[optlen]; strncpy(optstr_buf, args.argv[optind - 1], optlen); options._optstr = ramfs_parse_options(optstr_buf, options); - delete optstr_buf; + delete[] optstr_buf; /* Mark for erase of -o arg if the output option str is empty */ if (strnlen(options._optstr, OPTION_MAX) == 0) { argo_idx = optind - 1; @@ -223,7 +224,7 @@ void ramfs_parse_cmdline(struct fuse_args &args, struct fuse_ramfs_options &opti } } else { if (args.allocated) { - delete args.argv[optind - 1]; + delete[] args.argv[optind - 1]; } args.argv[optind - 1] = options._optstr; } diff --git a/tests/compile.sh b/tests/compile.sh index 6157cfe..406d6f9 100644 --- a/tests/compile.sh +++ b/tests/compile.sh @@ -1,7 +1,7 @@ #!/bin/bash xargs rm < ../build/install_manifest.txt -rm -rf ../build/* +#rm -rf ../build/* cd ../build/ || exit cmake ../src make