]> git.hungrycats.org Git - bees/commitdiff
btrfs-tree: harden `rlower_bound` against exceptional objects
authorZygo Blaxell <bees@furryterror.org>
Tue, 28 Jan 2025 01:04:13 +0000 (20:04 -0500)
committerZygo Blaxell <bees@furryterror.org>
Fri, 7 Feb 2025 03:42:15 +0000 (22:42 -0500)
Rearrange the logic in `rlower_bound` so it can cope with a tree
that contains mostly block-aligned objects, with a few exceptions
filtered out by `hdr_stop`.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
lib/btrfs-tree.cc

index 2027e8b743da139de6a182004e89a3a2fe3f370b..aa8958fc16f8629b3ac6cf657231a6274d9a9b98 100644 (file)
@@ -413,8 +413,8 @@ namespace crucible {
                uint64_t closest_logical = 0;
                BtrfsIoctlSearchKey &sk = m_sk;
                size_t loops = 0;
-               BTFRLB_DEBUG("rlower_bound: " << to_hex(logical) << endl);
-               seek_backward(scale_logical(logical), [&](uint64_t lower_bound, uint64_t upper_bound) {
+               BTFRLB_DEBUG("rlower_bound: " << to_hex(logical) << " in tree " << tree() << endl);
+               seek_backward(scale_logical(logical), [&](uint64_t const lower_bound, uint64_t const upper_bound) {
                        ++loops;
                        fill_sk(sk, unscale_logical(min(scaled_max_logical(), lower_bound)));
                        set<uint64_t> rv;
@@ -424,29 +424,31 @@ namespace crucible {
                                BTFRLB_DEBUG("fetch: loop " << loops << " lower_bound..upper_bound " << to_hex(lower_bound) << ".." << to_hex(upper_bound));
                                for (auto &i : sk.m_result) {
                                        next_sk(sk, i);
+                                       // If hdr_stop or !hdr_match, don't inspect the item
+                                       if (hdr_stop(i)) {
+                                               rv.insert(numeric_limits<uint64_t>::max());
+                                               BTFRLB_DEBUG("(stop)");
+                                               break;
+                                       }
+                                       if (!hdr_match(i)) {
+                                               BTFRLB_DEBUG("(no match)");
+                                               continue;
+                                       }
                                        const auto this_logical = hdr_logical(i);
+                                       BTFRLB_DEBUG(" " << to_hex(this_logical) << " " << i);
                                        const auto scaled_hdr_logical = scale_logical(this_logical);
-                                       BTFRLB_DEBUG(" " << to_hex(scaled_hdr_logical));
-                                       if (hdr_match(i)) {
-                                               if (this_logical <= logical && this_logical > closest_logical) {
-                                                       closest_logical = this_logical;
-                                                       closest_item = i;
-                                               }
-                                               BTFRLB_DEBUG("(match)");
-                                               rv.insert(scaled_hdr_logical);
+                                       BTFRLB_DEBUG(" " << "(match)");
+                                       if (this_logical <= logical && this_logical > closest_logical) {
+                                               closest_logical = this_logical;
+                                               closest_item = i;
+                                               BTFRLB_DEBUG("(closest)");
                                        }
-                                       if (scaled_hdr_logical > upper_bound || hdr_stop(i)) {
-                                               if (scaled_hdr_logical >= upper_bound) {
-                                                       BTFRLB_DEBUG("(" << to_hex(scaled_hdr_logical) << " >= " << to_hex(upper_bound) << ")");
-                                               }
-                                               if (hdr_stop(i)) {
-                                                       rv.insert(numeric_limits<uint64_t>::max());
-                                                       BTFRLB_DEBUG("(stop)");
-                                               }
+                                       rv.insert(scaled_hdr_logical);
+                                       if (scaled_hdr_logical > upper_bound) {
+                                               BTFRLB_DEBUG("(" << to_hex(scaled_hdr_logical) << " >= " << to_hex(upper_bound) << ")");
                                                break;
-                                       } else {
-                                               BTFRLB_DEBUG("(cont'd)");
                                        }
+                                       BTFRLB_DEBUG("(cont'd)");
                                }
                                BTFRLB_DEBUG(endl);
                                // We might get a search result that contains only non-matching items.