From 62f83869f1265c4411a51a37dcbe418469fd2581 Mon Sep 17 00:00:00 2001 From: Patrick Insinger Date: Wed, 29 Sep 2021 16:19:45 -0700 Subject: [PATCH] pageserver - fsync image/delta layers Ensure image and delta layer files are durable. Also, fsync the parent directory to ensure the directory entries are durable. --- pageserver/src/layered_repository.rs | 17 +++++++++++++++++ .../src/layered_repository/delta_layer.rs | 3 ++- .../src/layered_repository/image_layer.rs | 3 ++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pageserver/src/layered_repository.rs b/pageserver/src/layered_repository.rs index 0cf4fe9359..b2984d5337 100644 --- a/pageserver/src/layered_repository.rs +++ b/pageserver/src/layered_repository.rs @@ -1311,6 +1311,8 @@ impl LayeredTimeline { last_record_lsn ); + let timeline_dir = File::open(self.conf.timeline_path(&self.timelineid, &self.tenantid))?; + // Take the in-memory layer with the oldest WAL record. If it's older // than the threshold, write it out to disk as a new image and delta file. // Repeat until all remaining in-memory layers are within the threshold. @@ -1322,6 +1324,8 @@ impl LayeredTimeline { // a lot of memory and/or aren't receiving much updates anymore. let mut disk_consistent_lsn = last_record_lsn; + let mut created_historics = false; + while let Some((oldest_layer, oldest_generation)) = layers.peek_oldest_open() { let oldest_pending_lsn = oldest_layer.get_oldest_pending_lsn(); @@ -1374,6 +1378,11 @@ impl LayeredTimeline { drop(layers); let new_historics = frozen.write_to_disk(self)?; layers = self.layers.lock().unwrap(); + + if !new_historics.is_empty() { + created_historics = true; + } + if let Some(relish_uploader) = &self.relish_uploader { for label_path in new_historics.iter().filter_map(|layer| layer.path()) { relish_uploader.schedule_upload(self.timelineid, label_path); @@ -1409,6 +1418,14 @@ impl LayeredTimeline { layer.unload()?; } + drop(layers); + + if created_historics { + // We must fsync the timeline dir to ensure the directory entries for + // new layer files are durable + timeline_dir.sync_all()?; + } + // Save the metadata, with updated 'disk_consistent_lsn', to a // file in the timeline dir. After crash, we will restart WAL // streaming and processing from that point. diff --git a/pageserver/src/layered_repository/delta_layer.rs b/pageserver/src/layered_repository/delta_layer.rs index cf1abf741f..63be220716 100644 --- a/pageserver/src/layered_repository/delta_layer.rs +++ b/pageserver/src/layered_repository/delta_layer.rs @@ -487,7 +487,8 @@ impl DeltaLayer { let book = chapter.close()?; // This flushes the underlying 'buf_writer'. - book.close()?; + let writer = book.close()?; + writer.get_ref().sync_all()?; trace!("saved {}", &path.display()); diff --git a/pageserver/src/layered_repository/image_layer.rs b/pageserver/src/layered_repository/image_layer.rs index 3da19e6a53..a9487a02d4 100644 --- a/pageserver/src/layered_repository/image_layer.rs +++ b/pageserver/src/layered_repository/image_layer.rs @@ -337,7 +337,8 @@ impl ImageLayer { let book = chapter.close()?; // This flushes the underlying 'buf_writer'. - book.close()?; + let writer = book.close()?; + writer.get_ref().sync_all()?; trace!("saved {}", &path.display());