mirror of
https://github.com/Zygo/bees.git
synced 2025-08-01 13:23:28 +02:00
roots: filter out NODATASUM files before attempting to scan them
Add a cheap check for `FS_NOCOW_FL` when we first encounter each extent. In the raw btrfs inode flags, the offending flag is `BTRFS_INODE_NODATASUM`, because the restriction that prevents reflink between datacow and "nodatacow" files is that a single inode is allowed to have csums or not have csums, but must apply that choice to _all_ of its extents. This extra check is cheaper than opening a file for each individual reference to the extent, and then discovering that the file is `FS_NOCOW_FL`, and then closing the file, over and over again. It will also avoid emitting a lot of noisy log messages. Fixes: https://github.com/Zygo/bees/issues/313 Signed-off-by: Zygo Blaxell <bees@furryterror.org>
This commit is contained in:
@@ -183,26 +183,41 @@ BeesScanModeSubvol::crawl_one_inode(const shared_ptr<BeesCrawl>& this_crawl)
|
|||||||
}
|
}
|
||||||
const auto subvol = this_range.fid().root();
|
const auto subvol = this_range.fid().root();
|
||||||
const auto inode = this_range.fid().ino();
|
const auto inode = this_range.fid().ino();
|
||||||
ostringstream oss;
|
bool run_the_task = false;
|
||||||
oss << "crawl_" << subvol << "_" << inode;
|
catch_all([&]() {
|
||||||
const auto task_title = oss.str();
|
BtrfsInodeFetcher inode_btf(m_ctx->root_fd());
|
||||||
const auto bfc = make_shared<BeesFileCrawl>((BeesFileCrawl) {
|
const auto inode_item = inode_btf.stat(subvol, inode);
|
||||||
.m_ctx = m_ctx,
|
if (!!inode_item) {
|
||||||
.m_crawl = this_crawl,
|
const auto flags = inode_item.inode_flags();
|
||||||
.m_roots = m_roots,
|
if (0 != (flags & BTRFS_INODE_NODATASUM)) {
|
||||||
.m_hold = this_crawl->hold_state(this_state),
|
BEESLOGDEBUG("unsupported inode flags for ref at root " << subvol << " ino " << inode << ": " << btrfs_inode_flags_ntoa(flags));
|
||||||
.m_state = this_state,
|
} else {
|
||||||
.m_offset = this_range.begin(),
|
run_the_task = true;
|
||||||
});
|
}
|
||||||
BEESNOTE("Starting task " << this_range);
|
|
||||||
Task(task_title, [bfc]() {
|
|
||||||
BEESNOTE("crawl_one_inode " << bfc->m_hold->get());
|
|
||||||
if (bfc->scan_one_ref()) {
|
|
||||||
// Append the current task to itself to make
|
|
||||||
// sure we keep a worker processing this file
|
|
||||||
Task::current_task().append(Task::current_task());
|
|
||||||
}
|
}
|
||||||
}).run();
|
});
|
||||||
|
if (run_the_task) {
|
||||||
|
ostringstream oss;
|
||||||
|
oss << "crawl_" << subvol << "_" << inode;
|
||||||
|
const auto task_title = oss.str();
|
||||||
|
const auto bfc = make_shared<BeesFileCrawl>((BeesFileCrawl) {
|
||||||
|
.m_ctx = m_ctx,
|
||||||
|
.m_crawl = this_crawl,
|
||||||
|
.m_roots = m_roots,
|
||||||
|
.m_hold = this_crawl->hold_state(this_state),
|
||||||
|
.m_state = this_state,
|
||||||
|
.m_offset = this_range.begin(),
|
||||||
|
});
|
||||||
|
BEESNOTE("Starting task " << this_range);
|
||||||
|
Task(task_title, [bfc]() {
|
||||||
|
BEESNOTE("crawl_one_inode " << bfc->m_hold->get());
|
||||||
|
if (bfc->scan_one_ref()) {
|
||||||
|
// Append the current task to itself to make
|
||||||
|
// sure we keep a worker processing this file
|
||||||
|
Task::current_task().append(Task::current_task());
|
||||||
|
}
|
||||||
|
}).run();
|
||||||
|
}
|
||||||
auto next_state = this_state;
|
auto next_state = this_state;
|
||||||
// Skip to EOF. Will repeat up to 16 times if there happens to be an extent at 16EB,
|
// Skip to EOF. Will repeat up to 16 times if there happens to be an extent at 16EB,
|
||||||
// which would be a neat trick given that off64_t is signed.
|
// which would be a neat trick given that off64_t is signed.
|
||||||
@@ -780,10 +795,27 @@ BeesScanModeExtent::SizeTier::create_extent_map(const uint64_t bytenr, const Pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
BtrfsExtentDataFetcher bedf(m_ctx->root_fd());
|
BtrfsExtentDataFetcher bedf(m_ctx->root_fd());
|
||||||
|
BtrfsInodeFetcher inode_btf(m_ctx->root_fd());
|
||||||
|
|
||||||
const auto refs_list = make_shared<list<ExtentRef>>();
|
const auto refs_list = make_shared<list<ExtentRef>>();
|
||||||
|
bool found_nocow = false;
|
||||||
|
bool check_nocow = true;
|
||||||
for (const auto &i : log_ino.m_iors) {
|
for (const auto &i : log_ino.m_iors) {
|
||||||
catch_all([&](){
|
catch_all([&](){
|
||||||
|
if (check_nocow) {
|
||||||
|
BEESTRACE("checking inode flags for extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum);
|
||||||
|
BEESNOTE("checking inode flags for extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum);
|
||||||
|
const auto inode_item = inode_btf.stat(i.m_root, i.m_inum);
|
||||||
|
if (!!inode_item) {
|
||||||
|
const auto flags = inode_item.inode_flags();
|
||||||
|
check_nocow = false;
|
||||||
|
if (0 != (flags & BTRFS_INODE_NODATASUM)) {
|
||||||
|
BEESLOGDEBUG("unsupported inode flags for extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum << ": " << btrfs_inode_flags_ntoa(flags));
|
||||||
|
found_nocow = true;
|
||||||
|
return; // from the catch_all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BEESTRACE("mapping extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum << " offset " << to_hex(i.m_offset));
|
BEESTRACE("mapping extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum << " offset " << to_hex(i.m_offset));
|
||||||
BEESNOTE("mapping extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum << " offset " << to_hex(i.m_offset));
|
BEESNOTE("mapping extent " << to_hex(bytenr) << " ref at root " << i.m_root << " ino " << i.m_inum << " offset " << to_hex(i.m_offset));
|
||||||
|
|
||||||
@@ -808,6 +840,11 @@ BeesScanModeExtent::SizeTier::create_extent_map(const uint64_t bytenr, const Pro
|
|||||||
refs_list->push_back(extref);
|
refs_list->push_back(extref);
|
||||||
BEESCOUNT(extent_ref_ok);
|
BEESCOUNT(extent_ref_ok);
|
||||||
});
|
});
|
||||||
|
// Completely abandon the extent if it is nodatasum
|
||||||
|
if (found_nocow) {
|
||||||
|
BEESCOUNT(extent_nodatasum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BEESCOUNT(extent_mapped);
|
BEESCOUNT(extent_mapped);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user