diff --git a/core/src/os_install/gpt.rs b/core/src/os_install/gpt.rs index 932538d98..9823f98d8 100644 --- a/core/src/os_install/gpt.rs +++ b/core/src/os_install/gpt.rs @@ -187,11 +187,32 @@ pub async fn partition( .invoke(crate::ErrorKind::DiskManagement) .await .ok(); - Command::new("blockdev") - .arg("--rereadpt") - .arg(&disk_path) - .invoke(crate::ErrorKind::DiskManagement) - .await?; + // BLKRRPART can fail with "Device or resource busy" if the kernel still + // holds references to old partitions. Retry a few times with a delay. + let mut last_err = None; + for attempt in 0..5u32 { + if attempt > 0 { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } + match Command::new("blockdev") + .arg("--rereadpt") + .arg(&disk_path) + .invoke(crate::ErrorKind::DiskManagement) + .await + { + Ok(_) => { + last_err = None; + break; + } + Err(e) => { + tracing::warn!("blockdev --rereadpt attempt {} failed: {e}", attempt + 1); + last_err = Some(e); + } + } + } + if let Some(e) = last_err { + return Err(e); + } Command::new("udevadm") .arg("settle") .invoke(crate::ErrorKind::DiskManagement) diff --git a/core/src/os_install/mbr.rs b/core/src/os_install/mbr.rs index 090fa9554..3e9de57e8 100644 --- a/core/src/os_install/mbr.rs +++ b/core/src/os_install/mbr.rs @@ -153,11 +153,32 @@ pub async fn partition( .invoke(crate::ErrorKind::DiskManagement) .await .ok(); - Command::new("blockdev") - .arg("--rereadpt") - .arg(&disk_path) - .invoke(crate::ErrorKind::DiskManagement) - .await?; + // BLKRRPART can fail with "Device or resource busy" if the kernel still + // holds references to old partitions. Retry a few times with a delay. + let mut last_err = None; + for attempt in 0..5u32 { + if attempt > 0 { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } + match Command::new("blockdev") + .arg("--rereadpt") + .arg(&disk_path) + .invoke(crate::ErrorKind::DiskManagement) + .await + { + Ok(_) => { + last_err = None; + break; + } + Err(e) => { + tracing::warn!("blockdev --rereadpt attempt {} failed: {e}", attempt + 1); + last_err = Some(e); + } + } + } + if let Some(e) = last_err { + return Err(e); + } Command::new("udevadm") .arg("settle") .invoke(crate::ErrorKind::DiskManagement)