[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",