From af250f77325413811dfaa8f11d57f054a44b0eb8 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Sun, 28 Jan 2018 23:00:56 -0500 Subject: [PATCH] roots: determine transid_max without open()ing every subvol root Scan the roots tree directly for roots other than 5 (the FS root), and use btrfs_get_root_transid on root_fd for root 5. This avoids filling up the root FD cache every time we want a new transid_max. Now the only reason we open a subvol root FD is to open a file within the subvol. transid_max may be the same as the FS root's transid, in which case the search loop is not necessary. Place a counter (transid_max_miss) to see if we ever need to look at root items. If this counter never goes above zero, or does so very rarely, we can delete the search loop. Signed-off-by: Zygo Blaxell --- src/bees-roots.cc | 50 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/bees-roots.cc b/src/bees-roots.cc index 728a810..5ad383e 100644 --- a/src/bees-roots.cc +++ b/src/bees-roots.cc @@ -196,22 +196,44 @@ BeesRoots::transid_min() uint64_t BeesRoots::transid_max_nocache() { - // FIXME: get transid_max from any of the many trees we are searching with - // TREE_SEARCH_V2. Here we are open()ing every subvol. - uint64_t rv = 0; - uint64_t root = 0; + uint64_t root = BTRFS_FS_TREE_OBJECTID; BEESNOTE("Calculating transid_max (" << rv << " as of root " << root << ")"); BEESTRACE("Calculating transid_max..."); - do { - root = next_root(root); - if (root) { - catch_all([&]() { - auto transid = btrfs_get_root_transid(open_root(root)); - rv = max(rv, transid); - }); + + rv = btrfs_get_root_transid(root); + + // XXX: Do we need any of this? Or is + // m_transid_re.update(btrfs_get_root_transid(BTRFS_FS_TREE_OBJECTID)) good enough? + + BtrfsIoctlSearchKey sk; + sk.tree_id = BTRFS_ROOT_TREE_OBJECTID; + sk.min_type = sk.max_type = BTRFS_ROOT_BACKREF_KEY; + sk.min_objectid = root; + + while (true) { + sk.nr_items = 1024; + sk.do_ioctl(m_ctx->root_fd()); + + if (sk.m_result.empty()) { + break; } - } while (root); + + for (auto i : sk.m_result) { + sk.next_min(i); + if (i.type == BTRFS_ROOT_BACKREF_KEY) { + if (i.transid > rv) { + BEESLOGDEBUG("transid_max root " << i.objectid << " parent " << i.offset << " transid " << i.transid); + BEESCOUNT(transid_max_miss); + } + root = i.objectid; + } + if (i.transid > rv) { + rv = i.transid; + } + } + } + m_transid_re.update(rv); return rv; } @@ -634,7 +656,7 @@ BeesRoots::next_root(uint64_t root) // BTRFS_FS_TREE_OBJECTID has no backref keys so we can't find it that way if (root < BTRFS_FS_TREE_OBJECTID) { - // BEESLOG("First root is BTRFS_FS_TREE_OBJECTID = " << BTRFS_FS_TREE_OBJECTID); + // BEESLOGDEBUG("First root is BTRFS_FS_TREE_OBJECTID = " << BTRFS_FS_TREE_OBJECTID); return BTRFS_FS_TREE_OBJECTID; } @@ -654,7 +676,7 @@ BeesRoots::next_root(uint64_t root) for (auto i : sk.m_result) { sk.next_min(i); if (i.type == BTRFS_ROOT_BACKREF_KEY) { - // BEESLOG("Found root " << i.objectid << " parent " << i.offset); + // BEESLOGDEBUG("Found root " << i.objectid << " parent " << i.offset << " transid " << i.transid); return i.objectid; } }