mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-08 11:59:48 -04:00
fix(dwarfs): limit number of chunks in inodeinfo xattr
Highly fragmented files would have *megabytes* in `inodeinfo`, which not only breaks the xattr interface, but can also dramatically slow down tools like `eza` who like to read xattrs for no apparent reason.
This commit is contained in:
parent
e803efebe6
commit
a8cf283d4e
@ -320,6 +320,10 @@ class filesystem_v2 {
|
||||
return impl_->get_inode_info(entry);
|
||||
}
|
||||
|
||||
nlohmann::json get_inode_info(inode_view entry, size_t max_chunks) const {
|
||||
return impl_->get_inode_info(entry, max_chunks);
|
||||
}
|
||||
|
||||
std::vector<std::string> get_all_block_categories() const {
|
||||
return impl_->get_all_block_categories();
|
||||
}
|
||||
@ -426,6 +430,8 @@ class filesystem_v2 {
|
||||
virtual bool has_symlinks() const = 0;
|
||||
virtual history const& get_history() const = 0;
|
||||
virtual nlohmann::json get_inode_info(inode_view entry) const = 0;
|
||||
virtual nlohmann::json
|
||||
get_inode_info(inode_view entry, size_t max_chunks) const = 0;
|
||||
virtual std::vector<std::string> get_all_block_categories() const = 0;
|
||||
virtual std::vector<file_stat::uid_type> get_all_uids() const = 0;
|
||||
virtual std::vector<file_stat::gid_type> get_all_gids() const = 0;
|
||||
|
@ -151,8 +151,8 @@ class metadata_v2 {
|
||||
|
||||
bool has_symlinks() const { return impl_->has_symlinks(); }
|
||||
|
||||
nlohmann::json get_inode_info(inode_view iv) const {
|
||||
return impl_->get_inode_info(iv);
|
||||
nlohmann::json get_inode_info(inode_view iv, size_t max_chunks) const {
|
||||
return impl_->get_inode_info(iv, max_chunks);
|
||||
}
|
||||
|
||||
std::optional<std::string> get_block_category(size_t block_number) const {
|
||||
@ -229,7 +229,8 @@ class metadata_v2 {
|
||||
|
||||
virtual bool has_symlinks() const = 0;
|
||||
|
||||
virtual nlohmann::json get_inode_info(inode_view iv) const = 0;
|
||||
virtual nlohmann::json
|
||||
get_inode_info(inode_view iv, size_t max_chunks) const = 0;
|
||||
|
||||
virtual std::optional<std::string>
|
||||
get_block_category(size_t block_number) const = 0;
|
||||
|
@ -290,7 +290,11 @@ class filesystem_ final : public filesystem_v2::impl {
|
||||
bool has_symlinks() const override { return meta_.has_symlinks(); }
|
||||
history const& get_history() const override { return history_; }
|
||||
nlohmann::json get_inode_info(inode_view entry) const override {
|
||||
return meta_.get_inode_info(entry);
|
||||
return meta_.get_inode_info(entry, std::numeric_limits<size_t>::max());
|
||||
}
|
||||
nlohmann::json
|
||||
get_inode_info(inode_view entry, size_t max_chunks) const override {
|
||||
return meta_.get_inode_info(entry, max_chunks);
|
||||
}
|
||||
std::vector<std::string> get_all_block_categories() const override {
|
||||
return meta_.get_all_block_categories();
|
||||
|
@ -529,7 +529,8 @@ class metadata_ final : public metadata_v2::impl {
|
||||
|
||||
bool has_symlinks() const override { return !meta_.symlink_table().empty(); }
|
||||
|
||||
nlohmann::json get_inode_info(inode_view iv) const override;
|
||||
nlohmann::json
|
||||
get_inode_info(inode_view iv, size_t max_chunks) const override;
|
||||
|
||||
std::optional<std::string>
|
||||
get_block_category(size_t block_number) const override;
|
||||
@ -1844,7 +1845,9 @@ metadata_<LoggerPolicy>::get_chunks(int inode, std::error_code& ec) const {
|
||||
}
|
||||
|
||||
template <typename LoggerPolicy>
|
||||
nlohmann::json metadata_<LoggerPolicy>::get_inode_info(inode_view iv) const {
|
||||
nlohmann::json
|
||||
metadata_<LoggerPolicy>::get_inode_info(inode_view iv,
|
||||
size_t max_chunks) const {
|
||||
nlohmann::json obj;
|
||||
|
||||
if (iv.is_regular_file()) {
|
||||
@ -1854,16 +1857,20 @@ nlohmann::json metadata_<LoggerPolicy>::get_inode_info(inode_view iv) const {
|
||||
DWARFS_CHECK(!ec, fmt::format("get_chunk_range({}): {}", iv.inode_num(),
|
||||
ec.message()));
|
||||
|
||||
for (auto const& chunk : chunk_range) {
|
||||
nlohmann::json& chk = obj["chunks"].emplace_back();
|
||||
if (chunk_range.size() <= max_chunks) {
|
||||
for (auto const& chunk : chunk_range) {
|
||||
nlohmann::json& chk = obj["chunks"].emplace_back();
|
||||
|
||||
chk["block"] = chunk.block();
|
||||
chk["offset"] = chunk.offset();
|
||||
chk["size"] = chunk.size();
|
||||
chk["block"] = chunk.block();
|
||||
chk["offset"] = chunk.offset();
|
||||
chk["size"] = chunk.size();
|
||||
|
||||
if (auto catname = get_block_category(chunk.block())) {
|
||||
chk["category"] = catname.value();
|
||||
if (auto catname = get_block_category(chunk.block())) {
|
||||
chk["category"] = catname.value();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obj["chunks"] = fmt::format("too many chunks ({})", chunk_range.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,7 @@ namespace {
|
||||
|
||||
constexpr size_t const kDefaultBlockSize{static_cast<size_t>(512) << 10};
|
||||
constexpr size_t const kDefaultSeqDetectorThreshold{4};
|
||||
constexpr size_t const kMaxInodeInfoChunks{8};
|
||||
|
||||
struct options {
|
||||
// std::string isn't standard-layout on MSVC
|
||||
@ -952,7 +953,7 @@ int op_getxattr_common(LogProxy& log_, dwarfs_userdata& userdata,
|
||||
}
|
||||
|
||||
if (name == inodeinfo_xattr) {
|
||||
oss << userdata.fs.get_inode_info(*entry) << "\n";
|
||||
oss << userdata.fs.get_inode_info(*entry, kMaxInodeInfoChunks) << "\n";
|
||||
}
|
||||
|
||||
value = oss.str();
|
||||
|
Loading…
x
Reference in New Issue
Block a user