diff options
| -rw-r--r-- | src/src/vfs/mo2filesystem.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/src/vfs/mo2filesystem.cpp b/src/src/vfs/mo2filesystem.cpp index dd025f1..84f0471 100644 --- a/src/src/vfs/mo2filesystem.cpp +++ b/src/src/vfs/mo2filesystem.cpp @@ -47,6 +47,7 @@ void invalidateLookupCache(Mo2FsContext* ctx, const std::string& dirPath); void invalidateAttrCache(Mo2FsContext* ctx, fuse_ino_t ino); bool pathTouchesMutation(const std::string& cachedPath, const std::string& changedPath); +bool shouldTracePath(const std::string& path); int fuseErrnoFromError(std::error_code ec, int fallback = EIO) { @@ -485,6 +486,13 @@ bool pathTouchesMutation(const std::string& cachedPath, const std::string& chang isStrictDescendantPath(changedPath, cachedPath); } +bool shouldTracePath(const std::string& path) +{ + const std::string lower = normalizeForLookup(path); + return lower.ends_with(".hkx") || + lower.find("meshes/actors/") != std::string::npos; +} + // Clear all node_cache entries whose path is |path|, any descendant under // |path|/, or any ancestor of |path|. Must be called while tree_mutex is held // exclusively during mutations. @@ -1988,6 +1996,7 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) std::string realPath = snap.real_path; const bool writable = isWritableOpen(fi->flags); const bool truncateOnOpen = writable && ((fi->flags & O_TRUNC) != 0); + const bool tracePath = shouldTracePath(path); bool isBacking = snap.is_backing; bool cowPending = false; bool isTracked = false; @@ -2012,6 +2021,16 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) int fd = -1; if (writable) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open writable path='%s' real='%s' flags=0x%x " + "truncate=%d backing=%d origin='%s' size=%llu mode=%o\n", + path.c_str(), realPath.c_str(), fi->flags, + truncateOnOpen ? 1 : 0, isBacking ? 1 : 0, + snap.origin.c_str(), + static_cast<unsigned long long>(snap.size), + static_cast<unsigned int>(snap.cached_mode)); + } const std::string stagedPath = ctx->overwrite->stagingPath(path); const std::string owPath = ctx->overwrite->overwritePath(path); bool alreadyStaged = (realPath == stagedPath || realPath == owPath); @@ -2033,6 +2052,11 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) } fd = open(modFilePath.c_str(), openFlags); if (fd >= 0) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open tracked ok path='%s' real='%s' fd=%d\n", + path.c_str(), modFilePath.c_str(), fd); + } realPath = modFilePath; isTracked = true; if (truncateOnOpen) { @@ -2045,6 +2069,13 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) fuse_lowlevel_notify_inval_inode(ctx->session, ino, 0, 0); } } else { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open tracked failed path='%s' real='%s' errno=%d " + "message='%s'\n", + path.c_str(), modFilePath.c_str(), errno, + std::strerror(errno)); + } // Mod file disappeared — fall through to normal handling trackedMod.clear(); } @@ -2058,6 +2089,11 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) } fd = open(realPath.c_str(), openFlags); if (fd >= 0 && truncateOnOpen) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open staged truncate ok path='%s' real='%s' fd=%d\n", + path.c_str(), realPath.c_str(), fd); + } openSize = 0; openMtime = std::chrono::system_clock::now(); updateFileNodeKnown(ctx, path, realPath, originForPath(ctx, realPath), @@ -2067,6 +2103,12 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) } else if (fd < 0 && truncateOnOpen) { try { std::string newPath; + if (tracePath) { + std::fprintf(stderr, + "[VFS] open truncate COW begin path='%s' source='%s' " + "backing=%d\n", + path.c_str(), realPath.c_str(), isBacking ? 1 : 0); + } if (isBacking && ctx->backing_dir_fd >= 0) { newPath = ctx->overwrite->copyOnWriteFromFd(ctx->backing_dir_fd, path); } else { @@ -2075,6 +2117,11 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) fd = open(newPath.c_str(), O_RDWR | O_CLOEXEC | O_TRUNC); if (fd >= 0) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open truncate COW ok path='%s' staging='%s' fd=%d\n", + path.c_str(), newPath.c_str(), fd); + } realPath = newPath; isBacking = false; cowPending = false; @@ -2087,7 +2134,22 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) // and see the staging content, not the pre-COW cached data. fuse_lowlevel_notify_inval_inode(ctx->session, ino, 0, 0); } + } catch (const std::exception& e) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open truncate COW exception path='%s' source='%s' " + "what='%s'\n", + path.c_str(), realPath.c_str(), e.what()); + } + fuse_reply_err(req, EIO); + return; } catch (...) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open truncate COW unknown exception path='%s' " + "source='%s'\n", + path.c_str(), realPath.c_str()); + } fuse_reply_err(req, EIO); return; } @@ -2099,9 +2161,23 @@ void mo2_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) } else { fd = open(realPath.c_str(), O_RDONLY | O_CLOEXEC); } + if (tracePath && fd < 0) { + std::fprintf(stderr, + "[VFS] open lazy COW source failed path='%s' real='%s' " + "backing=%d errno=%d message='%s'\n", + path.c_str(), realPath.c_str(), isBacking ? 1 : 0, + errno, std::strerror(errno)); + } cowPending = true; } if (fd < 0) { + if (tracePath) { + std::fprintf(stderr, + "[VFS] open final failed path='%s' real='%s' errno=%d " + "message='%s'\n", + path.c_str(), realPath.c_str(), errno, + std::strerror(errno)); + } fuse_reply_err(req, errno != 0 ? errno : EIO); return; } @@ -2601,6 +2677,13 @@ void mo2_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, } if ((to_set & FUSE_SET_ATTR_SIZE) != 0 && attr != nullptr) { + if (shouldTracePath(path)) { + std::fprintf(stderr, + "[VFS] setattr size path='%s' size=%llu fh=%llu\n", + path.c_str(), + static_cast<unsigned long long>(attr->st_size), + static_cast<unsigned long long>(fi != nullptr ? fi->fh : 0)); + } std::string target; bool targetIsBacking = false; uint64_t fh = 0; @@ -2687,6 +2770,13 @@ void mo2_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, auto it = ctx->open_files.find(fh); if (it != ctx->open_files.end() && it->second.fd >= 0) { if (ftruncate(it->second.fd, static_cast<off_t>(attr->st_size)) != 0) { + if (shouldTracePath(path)) { + std::fprintf(stderr, + "[VFS] setattr ftruncate failed path='%s' target='%s' " + "errno=%d message='%s'\n", + path.c_str(), target.c_str(), errno, + std::strerror(errno)); + } fuse_reply_err(req, EIO); return; } @@ -2698,6 +2788,13 @@ void mo2_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, std::error_code ec; fs::resize_file(target, static_cast<uint64_t>(attr->st_size), ec); if (ec) { + if (shouldTracePath(path)) { + std::fprintf(stderr, + "[VFS] setattr resize failed path='%s' target='%s' " + "error=%d message='%s'\n", + path.c_str(), target.c_str(), ec.value(), + ec.message().c_str()); + } fuse_reply_err(req, EIO); return; } @@ -3164,10 +3261,29 @@ void mo2_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, int fd = -1; std::string relativePath; if (!ensureWritableOpenFile(ctx, fi->fh, ino, &fd, &relativePath)) { + std::string path; + bool ok = false; + path = inodeToPath(ctx, ino, &ok); + if (ok && shouldTracePath(path)) { + std::fprintf(stderr, + "[VFS] fallocate ensure writable failed path='%s' mode=0x%x " + "offset=%lld length=%lld errno=%d message='%s'\n", + path.c_str(), mode, static_cast<long long>(offset), + static_cast<long long>(length), errno, std::strerror(errno)); + } fuse_reply_err(req, errno != 0 ? errno : EIO); return; } + if (shouldTracePath(relativePath)) { + std::fprintf(stderr, + "[VFS] fallocate path='%s' fd=%d mode=0x%x offset=%lld " + "length=%lld\n", + relativePath.c_str(), fd, mode, + static_cast<long long>(offset), + static_cast<long long>(length)); + } + const off_t end = offset + length; if (length > 0 && end < offset) { fuse_reply_err(req, EFBIG); @@ -3187,6 +3303,14 @@ void mo2_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, } if (rc != 0) { + if (shouldTracePath(relativePath)) { + std::fprintf(stderr, + "[VFS] fallocate failed path='%s' fd=%d rc=%d mode=0x%x " + "offset=%lld length=%lld\n", + relativePath.c_str(), fd, rc, mode, + static_cast<long long>(offset), + static_cast<long long>(length)); + } fuse_reply_err(req, rc); return; } |
