From 6d742719a1b58d00abcd9bd2d81c97fed929cb23 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 4 Nov 2021 16:07:12 +0200 Subject: [PATCH] Fix infinite loop in looking up predecessor layer Commit 960c7d69a8 changed the LSN returned in the Continue case in InMemoryLayer::get_page_reconstruct_data(), but neglected to make the same change in DeltaLayer. Also add an escape hatch to the loop in materialize_page() to avoid getting stuck in an infinite loop, if a bug like this reoccurs. --- pageserver/src/layered_repository.rs | 9 +++++++++ pageserver/src/layered_repository/delta_layer.rs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pageserver/src/layered_repository.rs b/pageserver/src/layered_repository.rs index 38b33a361e..665840cba8 100644 --- a/pageserver/src/layered_repository.rs +++ b/pageserver/src/layered_repository.rs @@ -1534,6 +1534,15 @@ impl LayeredTimeline { PageReconstructResult::Continue(cont_lsn) => { // Fetch base image / more WAL from the returned predecessor layer if let Some((cont_layer, cont_lsn)) = self.get_layer_for_read(seg, cont_lsn)? { + if cont_lsn == curr_lsn { + // We landed on the same layer again. Shouldn't happen, but if it does, + // don't get stuck in an infinite loop. + bail!( + "could not find predecessor layer of segment {} at {}", + seg.rel, + cont_lsn + ); + } layer_arc = cont_layer; layer_ref = &*layer_arc; curr_lsn = cont_lsn; diff --git a/pageserver/src/layered_repository/delta_layer.rs b/pageserver/src/layered_repository/delta_layer.rs index 9f975cbd91..4e10a284ac 100644 --- a/pageserver/src/layered_repository/delta_layer.rs +++ b/pageserver/src/layered_repository/delta_layer.rs @@ -230,7 +230,7 @@ impl Layer for DeltaLayer { // If an older page image is needed to reconstruct the page, let the // caller know. if need_image { - Ok(PageReconstructResult::Continue(self.start_lsn)) + Ok(PageReconstructResult::Continue(Lsn(self.start_lsn.0 - 1))) } else { Ok(PageReconstructResult::Complete) }