[installer] Pause block watcher when writing FVM. Otherwise fshost tries to start blobfs while it's being written, which causes filesystem corruption. Change-Id: Ia63fb19b9f9233be7b80fe8f742e7b021c30c988
diff --git a/src/recovery/system/BUILD.gn b/src/recovery/system/BUILD.gn index cab04f0..05a78d7 100644 --- a/src/recovery/system/BUILD.gn +++ b/src/recovery/system/BUILD.gn
@@ -221,6 +221,7 @@ with_unit_tests = true deps = [ "//sdk/fidl/fuchsia.device:fuchsia.device-rustc", + "//sdk/fidl/fuchsia.fshost:fuchsia.fshost-rustc", "//sdk/fidl/fuchsia.hardware.block:fuchsia.hardware.block-rustc", "//sdk/fidl/fuchsia.hardware.block.partition:fuchsia.hardware.block.partition-rustc", "//sdk/fidl/fuchsia.hardware.block.volume:fuchsia.hardware.block.volume-rustc",
diff --git a/src/recovery/system/installer/partition.rs b/src/recovery/system/installer/partition.rs index 5d47598..c7ec364 100644 --- a/src/recovery/system/installer/partition.rs +++ b/src/recovery/system/installer/partition.rs
@@ -6,6 +6,7 @@ crate::installer::BootloaderType, anyhow::{anyhow, Context, Error}, fidl::endpoints::Proxy, + fidl_fuchsia_fshost::{BlockWatcherMarker, BlockWatcherProxy}, fidl_fuchsia_hardware_block_partition::PartitionProxy, fidl_fuchsia_mem::Buffer, fidl_fuchsia_paver::{Asset, Configuration, DynamicDataSinkProxy, PayloadStreamMarker}, @@ -16,6 +17,31 @@ std::{fmt, fs, io::Read, path::Path}, }; +struct BlockWatcherPauser { + proxy: Option<BlockWatcherProxy>, +} + +impl BlockWatcherPauser { + pub async fn new() -> Result<Self, Error> { + let connection = fuchsia_component::client::connect_to_protocol::<BlockWatcherMarker>() + .context("Connecting to block watcher")?; + zx::Status::ok(connection.pause().await.context("Sending pause")?) + .context("Pausing block watcher")?; + Ok(BlockWatcherPauser { proxy: Some(connection) }) + } + + pub async fn resume(mut self) -> Result<(), Error> { + zx::Status::ok(self.proxy.take().unwrap().resume().await.context("Sending resume")?) + .context("Resuming block watcher") + } +} + +impl Drop for BlockWatcherPauser { + fn drop(&mut self) { + assert!(self.proxy.is_none()) + } +} + #[derive(Debug, PartialEq)] pub enum PartitionPaveType { Asset { r#type: Asset, config: Configuration }, @@ -195,6 +221,7 @@ data_sink.write_bootloader(&mut fidl_buf).await?; } PartitionPaveType::Volume => { + let pauser = BlockWatcherPauser::new().await.context("Pausing block watcher")?; // Set up a PayloadStream to serve the data sink. let file = Box::new(fs::File::open(Path::new(&self.src)).context("Opening partition")?); @@ -214,6 +241,7 @@ .detach(); // Tell the data sink to use our PayloadStream. data_sink.write_volumes(client_end).await?; + pauser.resume().await.context("Resuming block watcher")?; } }; Ok(())
diff --git a/src/recovery/system/meta/system_recovery_installer.cmx b/src/recovery/system/meta/system_recovery_installer.cmx index a19e0bb..c7bff80 100644 --- a/src/recovery/system/meta/system_recovery_installer.cmx +++ b/src/recovery/system/meta/system_recovery_installer.cmx
@@ -23,6 +23,7 @@ "root-ssl-certificates" ], "services": [ + "fuchsia.fshost.BlockWatcher", "fuchsia.paver.Paver", "fuchsia.process.Launcher", "fuchsia.recovery.FactoryReset",