diff --git a/pageserver/ctl/src/layer_map_analyzer.rs b/pageserver/ctl/src/layer_map_analyzer.rs index 883762a273..5f4da7e474 100644 --- a/pageserver/ctl/src/layer_map_analyzer.rs +++ b/pageserver/ctl/src/layer_map_analyzer.rs @@ -99,6 +99,7 @@ async fn get_holes(path: &Path, max_holes: usize) -> Result> { let file = FileBlockReader::new(VirtualFile::open(path)?); let summary_blk = file.read_blk(0)?; let actual_summary = Summary::des_prefix(summary_blk.as_ref())?; + drop(summary_blk); let tree_reader = DiskBtreeReader::<_, DELTA_KEY_SIZE>::new( actual_summary.index_start_blk, actual_summary.index_root_blk, diff --git a/pageserver/src/page_cache.rs b/pageserver/src/page_cache.rs index e1e696ddad..b7aba96189 100644 --- a/pageserver/src/page_cache.rs +++ b/pageserver/src/page_cache.rs @@ -77,7 +77,7 @@ use std::{ convert::TryInto, sync::{ atomic::{AtomicU64, AtomicU8, AtomicUsize, Ordering}, - RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, + RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, TryLockResult, }, }; @@ -430,7 +430,27 @@ impl PageCache { for slot_idx in 0..self.slots.len() { let slot = &self.slots[slot_idx]; - let mut inner = slot.inner.write().unwrap(); + let mut inner = match slot.inner.try_write() { + TryLockResult::Ok(guard) => guard, + TryLockResult::Err(e @ TryLockError::Poisoned(_)) => { + panic!("slot lock {slot_idx} poisoned: {e:?}") + } + TryLockResult::Err(TryLockError::WouldBlock) => { + // This function is only called from the `Drop` impl of EphemeralFile. + // So, there shouldn't be any page cache users that are reading from + // that EphemeralFile anymore, because, + // 1. EphemeralFile doesn't hand out page cache read guards and + // 2. there can't be any concurrent `EphemeralFile::reads`s because it's being dropped. + // + // So, the only reason why the page is locked right now is `find_victim` + // trying to claim this page. + // + // Avoid waiting and keep the page in the cache. + // Sooner or later it'll become a victim and get evicted. + continue; + } + }; + if let Some(key) = &inner.key { match key { CacheKey::ImmutableFilePage { file_id, blkno: _ } diff --git a/pageserver/src/tenant/block_io.rs b/pageserver/src/tenant/block_io.rs index 3a6806357b..2e0382015e 100644 --- a/pageserver/src/tenant/block_io.rs +++ b/pageserver/src/tenant/block_io.rs @@ -36,7 +36,7 @@ where /// Reference to an in-memory copy of an immutable on-disk block. pub enum BlockLease<'a> { - PageReadGuard(PageReadGuard<'static>), + PageReadGuard(PageReadGuard<'a>), EphemeralFileMutableTail(&'a [u8; PAGE_SZ]), #[cfg(test)] Rc(std::rc::Rc<[u8; PAGE_SZ]>), diff --git a/pageserver/src/tenant/storage_layer/delta_layer.rs b/pageserver/src/tenant/storage_layer/delta_layer.rs index 7a482706e5..56c2c54b4f 100644 --- a/pageserver/src/tenant/storage_layer/delta_layer.rs +++ b/pageserver/src/tenant/storage_layer/delta_layer.rs @@ -848,6 +848,7 @@ impl DeltaLayerInner { let summary_blk = file.read_blk(0)?; let actual_summary = Summary::des_prefix(summary_blk.as_ref())?; + drop(summary_blk); if let Some(mut expected_summary) = summary { // production code path diff --git a/pageserver/src/tenant/storage_layer/image_layer.rs b/pageserver/src/tenant/storage_layer/image_layer.rs index cf4f40008a..b743daafd3 100644 --- a/pageserver/src/tenant/storage_layer/image_layer.rs +++ b/pageserver/src/tenant/storage_layer/image_layer.rs @@ -442,6 +442,7 @@ impl ImageLayerInner { let file = FileBlockReader::new(file); let summary_blk = file.read_blk(0)?; let actual_summary = Summary::des_prefix(summary_blk.as_ref())?; + drop(summary_blk); if let Some(mut expected_summary) = summary { // production code path