From af61b7238d2653c3b6f60c154be3f92edb5bfe60 Mon Sep 17 00:00:00 2001 From: Kosntantin Knizhnik Date: Sat, 12 Jul 2025 15:55:35 +0300 Subject: [PATCH] Set request_lsn=max(gc_cutoff,request_lsn) --- pageserver/src/page_service.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pageserver/src/page_service.rs b/pageserver/src/page_service.rs index 1fc7e4eac7..33aabe69b3 100644 --- a/pageserver/src/page_service.rs +++ b/pageserver/src/page_service.rs @@ -2167,7 +2167,7 @@ impl PageServerHandler { fn effective_request_lsn( timeline: &Timeline, last_record_lsn: Lsn, - request_lsn: Lsn, + mut request_lsn: Lsn, not_modified_since: Lsn, latest_gc_cutoff_lsn: &RcuReadGuard, ) -> Result { @@ -2195,12 +2195,14 @@ impl PageServerHandler { if request_lsn < **latest_gc_cutoff_lsn && !timeline.is_gc_blocked_by_lsn_lease_deadline() { let gc_info = &timeline.gc_info.read().unwrap(); if !gc_info.lsn_covered_by_lease(request_lsn) { - return Err( - PageStreamError::BadRequest(format!( - "tried to request a page version that was garbage collected. requested at {} gc cutoff {}", - request_lsn, **latest_gc_cutoff_lsn - ).into()) - ); + // While request was in flight, replica apply_lsn may be advanced. + // latest_gc_cutoff_lsn is conservative estimation for min(redo_lsn) for all replicas, + // so it is safe to move request_lsn forward to latest_gc_cutoff_lsn. + // If replica lease is expired and latest_gc_cutoff_lsn>redo_lsn for this replica, + // then check of page LSN at replia protects it from getting too new version of the page. + warn!("Tried to request a page version that was garbage collected. requested at {} gc cutoff {}", + request_lsn, **latest_gc_cutoff_lsn); + request_lsn = **latest_gc_cutoff_lsn; } }