| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/storage/blobfs/blobfs_inspect_tree.h" |
| |
| #include <atomic> |
| |
| #include "src/storage/blobfs/blobfs.h" |
| |
| namespace { |
| |
| inspect::Inspector CreateInspector() { |
| #ifdef BLOBFS_ENABLE_LARGE_INSPECT_VMO |
| // When recording page-in frequencies, a much larger Inspect VMO is required (>512KB). |
| // |
| // TODO(https://fxbug.dev/42137068): Inspect should print warnings about overflowing the maximum size of a |
| // VMO. |
| const size_t kMaxInspectVmoSize = 2UL * 1024UL * 1024UL; |
| return inspect::Inspector(inspect::InspectSettings{.maximum_size = kMaxInspectVmoSize}); |
| #else |
| // Use default inspect settings (currently sets the Inspect VMO size to 256KiB). |
| return inspect::Inspector(); |
| #endif |
| } |
| |
| } // namespace |
| |
| namespace blobfs { |
| |
| BlobfsInspectTree::BlobfsInspectTree() |
| : inspector_(CreateInspector()), |
| opstats_node_(inspector_.GetRoot().CreateChild("fs.opstats")), |
| node_operations_(opstats_node_), |
| detail_node_(inspector_.GetRoot().CreateChild(fs_inspect::kDetailNodeName)), |
| fragmentation_metrics_node_(detail_node_.CreateChild("fragmentation_metrics")), |
| compression_metrics_node_(detail_node_.CreateChild("compression_metrics")), |
| fs_inspect_nodes_(fs_inspect::CreateTree(inspector_.GetRoot(), CreateCallbacks())) {} |
| |
| // Set general filesystem information. |
| void BlobfsInspectTree::SetInfo(const fs_inspect::InfoData& info) { |
| std::lock_guard guard(info_mutex_); |
| info_ = info; |
| } |
| |
| // Update resource usage values that change when certain fields in the superblock are modified. |
| void BlobfsInspectTree::UpdateSuperblock(const Superblock& superblock) { |
| std::lock_guard guard(usage_mutex_); |
| usage_.total_bytes = superblock.data_block_count * superblock.block_size; |
| usage_.used_bytes = superblock.alloc_block_count * superblock.block_size; |
| usage_.total_nodes = superblock.inode_count; |
| usage_.used_nodes = superblock.alloc_inode_count; |
| } |
| |
| // Update FVM fvm information and record any out of space events. |
| void BlobfsInspectTree::UpdateFvmData(const block_client::BlockDevice& device, bool out_of_space) { |
| zx::result<fs_inspect::FvmData::SizeInfo> size_info = |
| fs_inspect::FvmData::GetSizeInfoFromDevice(device); |
| if (size_info.is_error()) { |
| FX_LOGS(WARNING) << "Failed to obtain size information from block device: " |
| << size_info.status_string(); |
| } |
| std::lock_guard guard(fvm_mutex_); |
| if (size_info.is_ok()) { |
| fvm_.size_info = size_info.value(); |
| } |
| if (out_of_space) { |
| ++fvm_.out_of_space_events; |
| } |
| } |
| |
| fs_inspect::NodeCallbacks BlobfsInspectTree::CreateCallbacks() { |
| return { |
| .info_callback = |
| [this] { |
| std::lock_guard guard(info_mutex_); |
| return info_; |
| }, |
| .usage_callback = |
| [this] { |
| std::lock_guard guard(usage_mutex_); |
| return usage_; |
| }, |
| .fvm_callback = |
| [this] { |
| std::lock_guard guard(fvm_mutex_); |
| return fvm_; |
| }, |
| }; |
| } |
| |
| void BlobfsInspectTree::CalculateFragmentationMetrics(Blobfs& blobfs) { |
| fragmentation_metrics_node_.AtomicUpdate([this, &blobfs](inspect::Node& node) { |
| fragmentation_metrics_ = FragmentationMetrics(node); |
| blobfs.CalculateFragmentationMetrics(fragmentation_metrics_); |
| }); |
| } |
| |
| void BlobfsInspectTree::UpdateCompressionMetrics(const CompressionMetrics& metrics) { |
| compression_metrics_node_.AtomicUpdate( |
| [this, &metrics](inspect::Node& node) { compression_metrics_ = metrics.Attach(node); }); |
| } |
| |
| } // namespace blobfs |