Loading src/client/gkfs_functions.cpp +40 −31 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ #include <client/cache.hpp> #include <string> #include <string_view> #include <mutex> #include <set> #include <tuple> #include <thread> Loading @@ -76,7 +77,10 @@ namespace { // set to store void * addr, fd, length and offset // set to store void * addr, fd, length, offset, prot // Protected by mmap_set_mutex for thread-safe access from parallel Python // threads std::set<std::tuple<void*, int, size_t, off_t, int>> mmap_set; std::mutex mmap_set_mutex; } // namespace Loading @@ -85,39 +89,45 @@ namespace gkfs::syscall { void* gkfs_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { if(length == 0) { errno = EINVAL; return MAP_FAILED; } void* ptr = calloc(1, length); if(ptr == nullptr) { return MAP_FAILED; } // store info on mmap_set mmap_set.insert(std::make_tuple(ptr, fd, length, offset, prot)); // Pre-populate the buffer from the GekkoFS file (read-write mapping) auto ret = gkfs::syscall::gkfs_pread(fd, ptr, length, offset); if(ret == -1) { mmap_set.erase(std::make_tuple(ptr, fd, length, offset, prot)); free(ptr); return MAP_FAILED; } // Register mapping under lock so concurrent threads don't race on mmap_set { std::lock_guard<std::mutex> lock(mmap_set_mutex); mmap_set.insert(std::make_tuple(ptr, fd, length, offset, prot)); } return ptr; } int // cppcheck-suppress constParameterPointer gkfs_msync(void* addr, size_t length, int flags) { // check if addr is from gekkofs (mmap_set) // if so, get the fd and offset // pwrite length to the original offset std::lock_guard<std::mutex> lock(mmap_set_mutex); // Find by start address; msync may pass a sub-range length so we use the // full mapping length stored in mmap_set. auto it = std::find_if( mmap_set.begin(), mmap_set.end(), [addr](const auto& t) { return std::get<0>(t) == addr; }); if(it != mmap_set.end()) { const auto& tuple = *it; int fd = std::get<1>(tuple); off_t offset = std::get<3>(tuple); int prot = std::get<4>(tuple); int fd = std::get<1>(*it); size_t map_length = std::get<2>(*it); // use stored length, not caller's off_t offset = std::get<3>(*it); int prot = std::get<4>(*it); if(prot & PROT_WRITE) { gkfs::syscall::gkfs_pwrite(fd, addr, length, offset); gkfs::syscall::gkfs_pwrite(fd, addr, map_length, offset); } return 0; } Loading @@ -127,27 +137,26 @@ gkfs_msync(void* addr, size_t length, int flags) { int gkfs_munmap(void* addr, size_t length) { // check if addr is from gekkofs (mmap_set) // if so, get the fd and offset // pwrite length to the original offset // return // if not just go to the normal msync if(mmap_set.size() != 0) { // use find_if std::algorithm // if found, call msync std::unique_lock<std::mutex> lock(mmap_set_mutex); auto it = std::find_if( mmap_set.begin(), mmap_set.end(), [&addr](const std::tuple<void*, int, size_t, off_t, int>& t) { return std::get<0>(t) == addr; }); if(it != mmap_set.end()) { gkfs_msync(addr, length, 0); free(addr); int fd = std::get<1>(*it); size_t map_length = std::get<2>(*it); off_t offset = std::get<3>(*it); int prot = std::get<4>(*it); // Flush dirty pages back before freeing if(prot & PROT_WRITE) { gkfs::syscall::gkfs_pwrite(fd, addr, map_length, offset); } mmap_set.erase(it); lock.unlock(); // release lock before free to avoid holding it longer free(addr); return 0; } } return -1; } Loading Loading
src/client/gkfs_functions.cpp +40 −31 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ #include <client/cache.hpp> #include <string> #include <string_view> #include <mutex> #include <set> #include <tuple> #include <thread> Loading @@ -76,7 +77,10 @@ namespace { // set to store void * addr, fd, length and offset // set to store void * addr, fd, length, offset, prot // Protected by mmap_set_mutex for thread-safe access from parallel Python // threads std::set<std::tuple<void*, int, size_t, off_t, int>> mmap_set; std::mutex mmap_set_mutex; } // namespace Loading @@ -85,39 +89,45 @@ namespace gkfs::syscall { void* gkfs_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { if(length == 0) { errno = EINVAL; return MAP_FAILED; } void* ptr = calloc(1, length); if(ptr == nullptr) { return MAP_FAILED; } // store info on mmap_set mmap_set.insert(std::make_tuple(ptr, fd, length, offset, prot)); // Pre-populate the buffer from the GekkoFS file (read-write mapping) auto ret = gkfs::syscall::gkfs_pread(fd, ptr, length, offset); if(ret == -1) { mmap_set.erase(std::make_tuple(ptr, fd, length, offset, prot)); free(ptr); return MAP_FAILED; } // Register mapping under lock so concurrent threads don't race on mmap_set { std::lock_guard<std::mutex> lock(mmap_set_mutex); mmap_set.insert(std::make_tuple(ptr, fd, length, offset, prot)); } return ptr; } int // cppcheck-suppress constParameterPointer gkfs_msync(void* addr, size_t length, int flags) { // check if addr is from gekkofs (mmap_set) // if so, get the fd and offset // pwrite length to the original offset std::lock_guard<std::mutex> lock(mmap_set_mutex); // Find by start address; msync may pass a sub-range length so we use the // full mapping length stored in mmap_set. auto it = std::find_if( mmap_set.begin(), mmap_set.end(), [addr](const auto& t) { return std::get<0>(t) == addr; }); if(it != mmap_set.end()) { const auto& tuple = *it; int fd = std::get<1>(tuple); off_t offset = std::get<3>(tuple); int prot = std::get<4>(tuple); int fd = std::get<1>(*it); size_t map_length = std::get<2>(*it); // use stored length, not caller's off_t offset = std::get<3>(*it); int prot = std::get<4>(*it); if(prot & PROT_WRITE) { gkfs::syscall::gkfs_pwrite(fd, addr, length, offset); gkfs::syscall::gkfs_pwrite(fd, addr, map_length, offset); } return 0; } Loading @@ -127,27 +137,26 @@ gkfs_msync(void* addr, size_t length, int flags) { int gkfs_munmap(void* addr, size_t length) { // check if addr is from gekkofs (mmap_set) // if so, get the fd and offset // pwrite length to the original offset // return // if not just go to the normal msync if(mmap_set.size() != 0) { // use find_if std::algorithm // if found, call msync std::unique_lock<std::mutex> lock(mmap_set_mutex); auto it = std::find_if( mmap_set.begin(), mmap_set.end(), [&addr](const std::tuple<void*, int, size_t, off_t, int>& t) { return std::get<0>(t) == addr; }); if(it != mmap_set.end()) { gkfs_msync(addr, length, 0); free(addr); int fd = std::get<1>(*it); size_t map_length = std::get<2>(*it); off_t offset = std::get<3>(*it); int prot = std::get<4>(*it); // Flush dirty pages back before freeing if(prot & PROT_WRITE) { gkfs::syscall::gkfs_pwrite(fd, addr, map_length, offset); } mmap_set.erase(it); lock.unlock(); // release lock before free to avoid holding it longer free(addr); return 0; } } return -1; } Loading