Browse Source

fix(rootfs): release loop device when fail to map partitions, change v1 back to original implmentation

Samuka007 19 hours ago
parent
commit
127af8bd95

+ 3 - 2
dadk/src/actions/rootfs/disk_img.rs

@@ -296,11 +296,12 @@ fn mount_partitioned_image_v1(
     let mut loop_device = ManuallyDrop::new(
         LoopDeviceBuilderV1::new()
             .img_path(disk_image_path)
-            .detach_on_drop(false)
             .build()
             .map_err(|e| anyhow!("Failed to create loop device: {}", e))?,
     );
 
+    loop_device.set_try_detach_when_drop(false);
+
     loop_device
         .attach()
         .map_err(|e| anyhow!("mount: Failed to attach loop device: {}", e))?;
@@ -450,9 +451,9 @@ fn create_partitioned_image_v2(ctx: &DADKExecContext, disk_image_path: &Path) ->
 pub fn show_loop_device_v1(ctx: &DADKExecContext) -> Result<()> {
     let disk_image_path = ctx.disk_image_path();
     let mut loop_device = LoopDeviceBuilderV1::new()
-        .detach_on_drop(false)
         .img_path(&disk_image_path)
         .build()?;
+    loop_device.set_try_detach_when_drop(false);
     if let Err(e) = loop_device.attach_by_exists() {
         log::error!("Failed to attach loop device: {}", e);
     } else {

+ 35 - 111
dadk/src/actions/rootfs/loopdev_v1.rs

@@ -17,11 +17,8 @@ pub struct LoopDevice {
     img_path: Option<PathBuf>,
     loop_device_path: Option<String>,
     /// 尝试在drop时自动detach
-    detach_on_drop: bool,
-    /// mapper created
-    mapper: bool,
+    try_detach_when_drop: bool,
 }
-
 impl LoopDevice {
     pub fn attached(&self) -> bool {
         self.loop_device_path.is_some()
@@ -103,36 +100,22 @@ impl LoopDevice {
     /// # 错误
     ///
     /// 如果循环设备未附加,则返回 `anyhow!("Loop device not attached")` 错误。
-    pub fn partition_path(&mut self, nth: u8) -> Result<PathBuf> {
+    pub fn partition_path(&self, nth: u8) -> Result<PathBuf> {
         if !self.attached() {
             return Err(anyhow!("Loop device not attached"));
         }
-        let dev_path = self.loop_device_path.as_ref().unwrap();
-        let direct_path = PathBuf::from(format!("{}p{}", dev_path, nth));
-
+        let s = format!("{}p{}", self.loop_device_path.as_ref().unwrap(), nth);
+        let s = PathBuf::from(s);
         // 判断路径是否存在
-        if !direct_path.exists() {
-            mapper::create_mapper(self.loop_device_path.as_ref().unwrap())?;
-            self.mapper = true;
-            let device_name = direct_path.file_name().unwrap();
-            let parent_path = direct_path.parent().unwrap();
-            let new_path = parent_path.join("mapper").join(device_name);
-            if new_path.exists() {
-                return Ok(new_path);
-            }
-            log::error!(
-                "Both {} and {} not exist!",
-                direct_path.display(),
-                new_path.display()
-            );
-            return Err(anyhow!("Unable to find partition path {}", nth));
+        if !s.exists() {
+            return Err(anyhow!("Partition not exist"));
         }
-        Ok(direct_path)
+        Ok(s)
     }
 
-    pub fn detach(&mut self) {
+    pub fn detach(&mut self) -> Result<()> {
         if self.loop_device_path.is_none() {
-            return;
+            return Ok(());
         }
         let loop_device = self.loop_device_path.take().unwrap();
         let p = PathBuf::from(&loop_device);
@@ -141,97 +124,39 @@ impl LoopDevice {
             p.display(),
             p.exists()
         );
+        let output = Command::new("losetup")
+            .arg("-d")
+            .arg(loop_device)
+            .output()?;
 
-        if self.mapper {
-            mapper::detach_mapper(&loop_device);
-            log::trace!("Detach mapper device: {}", &loop_device);
-            self.mapper = false;
-        }
-
-        let output = Command::new("losetup").arg("-d").arg(&loop_device).output();
-
-        if output.is_err() {
-            log::error!(
-                "losetup failed to detach loop device [{}]: {}",
-                &loop_device,
-                output.unwrap_err()
-            );
-            return;
-        }
-
-        let output = output.unwrap();
-
-        if !output.status.success() {
-            log::error!(
-                "losetup failed to detach loop device [{}]: {}, {}",
-                loop_device,
+        if output.status.success() {
+            self.loop_device_path = None;
+            Ok(())
+        } else {
+            Err(anyhow::anyhow!(
+                "Failed to detach loop device: {}, {}",
                 output.status,
                 str::from_utf8(output.stderr.as_slice()).unwrap_or("<Unknown>")
-            );
+            ))
         }
     }
 
-    #[allow(dead_code)]
-    pub fn detach_on_drop(&self) -> bool {
-        self.detach_on_drop
+    pub fn try_detach_when_drop(&self) -> bool {
+        self.try_detach_when_drop
     }
 
     #[allow(dead_code)]
     pub fn set_try_detach_when_drop(&mut self, try_detach_when_drop: bool) {
-        self.detach_on_drop = try_detach_when_drop;
+        self.try_detach_when_drop = try_detach_when_drop;
     }
 }
 
 impl Drop for LoopDevice {
     fn drop(&mut self) {
-        if self.detach_on_drop {
-            self.detach();
-        }
-    }
-}
-
-mod mapper {
-    use anyhow::anyhow;
-    use anyhow::Result;
-    use std::process::Command;
-
-    pub(super) fn create_mapper(dev_path: &str) -> Result<()> {
-        let output = Command::new("kpartx")
-            .arg("-a")
-            .arg("-v")
-            .arg(dev_path)
-            .output()
-            .map_err(|e| anyhow!("Failed to run kpartx: {}", e))?;
-        if output.status.success() {
-            let output_str = String::from_utf8(output.stdout)?;
-            log::trace!("kpartx output: {}", output_str);
-            return Ok(());
-        }
-        Err(anyhow!("Failed to create mapper"))
-    }
-
-    pub(super) fn detach_mapper(dev_path: &str) {
-        let output = Command::new("kpartx")
-            .arg("-d")
-            .arg("-v")
-            .arg(dev_path)
-            .output();
-        if output.is_ok() {
-            let output = output.unwrap();
-            if !output.status.success() {
-                log::error!(
-                    "kpartx failed to detach mapper device [{}]: {}, {}",
-                    dev_path,
-                    output.status,
-                    String::from_utf8(output.stderr).unwrap_or("<Unknown>".to_string())
-                );
+        if self.try_detach_when_drop() {
+            if let Err(e) = self.detach() {
+                log::warn!("Failed to detach loop device: {}", e);
             }
-        } else {
-            log::error!(
-                "Failed to detach mapper device [{}]: {}",
-                dev_path,
-                output.unwrap_err()
-            );
         }
     }
 }
@@ -239,7 +164,7 @@ mod mapper {
 pub struct LoopDeviceBuilder {
     img_path: Option<PathBuf>,
     loop_device_path: Option<String>,
-    detach_on_drop: bool,
+    try_detach_when_drop: bool,
 }
 
 impl LoopDeviceBuilder {
@@ -247,7 +172,7 @@ impl LoopDeviceBuilder {
         LoopDeviceBuilder {
             img_path: None,
             loop_device_path: None,
-            detach_on_drop: true,
+            try_detach_when_drop: true,
         }
     }
 
@@ -257,8 +182,8 @@ impl LoopDeviceBuilder {
     }
 
     #[allow(dead_code)]
-    pub fn detach_on_drop(mut self, detach_on_drop: bool) -> Self {
-        self.detach_on_drop = detach_on_drop;
+    pub fn try_detach_when_drop(mut self, try_detach_when_drop: bool) -> Self {
+        self.try_detach_when_drop = try_detach_when_drop;
         self
     }
 
@@ -266,8 +191,7 @@ impl LoopDeviceBuilder {
         let loop_dev = LoopDevice {
             img_path: self.img_path,
             loop_device_path: self.loop_device_path,
-            detach_on_drop: self.detach_on_drop,
-            mapper: false,
+            try_detach_when_drop: self.try_detach_when_drop,
         };
 
         Ok(loop_dev)
@@ -319,11 +243,11 @@ mod tests {
 
     #[test]
     fn test_parse_losetup_a_output() {
-        let losetup_a_output = r#"/dev/loop1: []: (/data/bin/x86_64/disk.img)
+        let losetup_a_output = r#"/dev/loop1: []: (/data/bin/disk-image-x86_64.img)
 /dev/loop29: []: (/var/lib/abc.img)
 /dev/loop13: []: (/var/lib/snapd/snaps/gtk-common-themes_1535.snap
 /dev/loop19: []: (/var/lib/snapd/snaps/gnome-42-2204_172.snap)"#;
-        let disk_img_path = "/data/bin/x86_64/disk.img";
+        let disk_img_path = "/data/bin/disk-image-x86_64.img";
         let loop_device_path =
             __loop_device_path_by_disk_image_path(disk_img_path, losetup_a_output).unwrap();
         assert_eq!(loop_device_path, "/dev/loop1");
@@ -331,11 +255,11 @@ mod tests {
 
     #[test]
     fn test_parse_lsblk_output_not_match() {
-        let losetup_a_output = r#"/dev/loop1: []: (/data/bin/x86_64/disk.img)
+        let losetup_a_output = r#"/dev/loop1: []: (/data/bin/disk-image-x86_64.img)
 /dev/loop29: []: (/var/lib/abc.img)
 /dev/loop13: []: (/var/lib/snapd/snaps/gtk-common-themes_1535.snap
 /dev/loop19: []: (/var/lib/snapd/snaps/gnome-42-2204_172.snap)"#;
-        let disk_img_path = "/data/bin/riscv64/disk.img";
+        let disk_img_path = "/data/bin/disk-image-riscv64.img";
         let loop_device_path =
             __loop_device_path_by_disk_image_path(disk_img_path, losetup_a_output);
         assert!(

+ 8 - 13
dadk/src/actions/rootfs/loopdev_v2.rs

@@ -48,7 +48,14 @@ impl LoopDevice {
             return Err(LoopError::LoopDeviceNotFound);
         }
 
-        let mapper = Mapper::new(path.clone(), detach_on_drop)?;
+        let mapper = Mapper::new(path.clone(), detach_on_drop).map_err(|err| {
+            log::error!("No loop mapper is available: {}", err);
+            let _ = LosetupCmd::new()
+                .arg("-d")
+                .arg(path.to_str().unwrap())
+                .output();
+            err
+        })?;
 
         Ok(Self {
             path,
@@ -64,16 +71,6 @@ impl LoopDevice {
     pub fn partition_path(&self, nth: u8) -> Result<PathBuf, LoopError> {
         self.mapper.partition_path(nth)
     }
-
-    // #[allow(dead_code)]
-    // pub fn detach_on_drop(&self) -> bool {
-    //     self.detach_on_drop
-    // }
-
-    // #[allow(dead_code)]
-    // pub fn set_detach_on_drop(&mut self, detach_on_drop: bool) {
-    //     self.detach_on_drop = detach_on_drop;
-    // }
 }
 impl Drop for LoopDevice {
     fn drop(&mut self) {
@@ -96,7 +93,6 @@ impl Drop for LoopDevice {
 
 pub struct LoopDeviceBuilder {
     img_path: Option<PathBuf>,
-    // loop_device_path: Option<String>,
     detach_on_drop: bool,
 }
 
@@ -104,7 +100,6 @@ impl LoopDeviceBuilder {
     pub fn new() -> Self {
         LoopDeviceBuilder {
             img_path: None,
-            // loop_device_path: None,
             detach_on_drop: true,
         }
     }