diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index 387de852..d3523cd0 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -174,6 +174,10 @@ class filesystem_v2 { history const& get_history() const { return impl_->get_history(); } + folly::dynamic get_inode_info(inode_view entry) const { + return impl_->get_inode_info(entry); + } + class impl { public: virtual ~impl() = default; @@ -214,6 +218,7 @@ class filesystem_v2 { virtual size_t num_blocks() const = 0; virtual bool has_symlinks() const = 0; virtual history const& get_history() const = 0; + virtual folly::dynamic get_inode_info(inode_view entry) const = 0; }; private: diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index b382638f..6db69982 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -134,6 +134,10 @@ class metadata_v2 { bool has_symlinks() const { return impl_->has_symlinks(); } + folly::dynamic get_inode_info(inode_view iv) const { + return impl_->get_inode_info(iv); + } + static std::pair, std::vector> freeze(const thrift::metadata::metadata& data); @@ -188,6 +192,8 @@ class metadata_v2 { virtual size_t block_size() const = 0; virtual bool has_symlinks() const = 0; + + virtual folly::dynamic get_inode_info(inode_view iv) const = 0; }; private: diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index ab5f2333..60ae6e61 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -387,6 +387,9 @@ class filesystem_ final : public filesystem_v2::impl { size_t num_blocks() const override { return ir_.num_blocks(); } bool has_symlinks() const override { return meta_.has_symlinks(); } history const& get_history() const override { return history_; } + folly::dynamic get_inode_info(inode_view entry) const override { + return meta_.get_inode_info(entry); + } private: filesystem_info const& get_info() const; diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 6aa23075..181d7ffa 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -447,6 +447,8 @@ class metadata_ final : public metadata_v2::impl { bool has_symlinks() const override { return !meta_.symlink_table().empty(); } + folly::dynamic get_inode_info(inode_view iv) const override; + private: template using set_type = folly::F14ValueSet; @@ -1525,6 +1527,40 @@ metadata_::get_chunks(int inode) const { return get_chunk_range(inode - inode_offset_); } +template +folly::dynamic metadata_::get_inode_info(inode_view iv) const { + folly::dynamic obj = folly::dynamic::object; + + auto chunk_range = get_chunk_range(iv.inode_num()); + + if (chunk_range) { + obj["chunks"] = folly::dynamic::array; + + for (auto const& chunk : *chunk_range) { + folly::dynamic chk = folly::dynamic::object; + + chk["block"] = chunk.block(); + chk["offset"] = chunk.offset(); + chk["size"] = chunk.size(); + + if (meta_.category_names() && meta_.block_categories()) { + chk["category"] = + meta_.category_names() + .value()[meta_.block_categories().value()[chunk.block()]]; + } + + obj["chunks"].push_back(chk); + } + } + + obj["mode"] = iv.mode(); + obj["modestring"] = modestring(iv.mode()); + obj["uid"] = iv.getuid(); + obj["gid"] = iv.getgid(); + + return obj; +} + std::pair, std::vector> metadata_v2::freeze(const thrift::metadata::metadata& data) { return freeze_to_buffer(data); diff --git a/src/dwarfs_main.cpp b/src/dwarfs_main.cpp index 66d2ddd9..85264887 100644 --- a/src/dwarfs_main.cpp +++ b/src/dwarfs_main.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #ifndef DWARFS_FUSE_LOWLEVEL #define DWARFS_FUSE_LOWLEVEL 1 @@ -182,6 +183,7 @@ namespace { constexpr std::string_view pid_xattr{"user.dwarfs.driver.pid"}; constexpr std::string_view perfmon_xattr{"user.dwarfs.driver.perfmon"}; +constexpr std::string_view inodeinfo_xattr{"user.dwarfs.inodeinfo"}; } // namespace @@ -828,6 +830,17 @@ void op_getxattr(fuse_req_t req, fuse_ino_t ino, char const* name, oss << "no performance monitor support\n"; #endif } + } else { + if (name == inodeinfo_xattr) { + auto entry = userdata->fs.find(ino); + + if (entry) { + auto ii = userdata->fs.get_inode_info(*entry); + oss << folly::toPrettyJson(ii) << "\n"; + } else { + err = ENOENT; + } + } } auto value = oss.view(); @@ -886,6 +899,8 @@ void op_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { if (ino == FUSE_ROOT_ID) { oss << pid_xattr << '\0'; oss << perfmon_xattr << '\0'; + } else { + oss << inodeinfo_xattr << '\0'; } auto xattrs = oss.view();