Blame SOURCES/s390x-support-virtio-dasd-0.9.1.patch

7dd7e2
From c4fabc7c801491019263523df3c9078cca99bb6e Mon Sep 17 00:00:00 2001
7dd7e2
From: Nikita Dubrovskii <nikita@linux.ibm.com>
7dd7e2
Date: Wed, 2 Jun 2021 14:27:42 +0200
7dd7e2
Subject: [PATCH] s390: add support for virtio dasds
7dd7e2
7dd7e2
This is a fix for https://bugzilla.redhat.com/show_bug.cgi?id=1960485
7dd7e2
7dd7e2
Signed-off-by: Nikita Dubrovskii <nikita@linux.ibm.com>
7dd7e2
---
7dd7e2
 src/blockdev.rs   | 30 ++++++++++++++++++++++++++++--
7dd7e2
 src/cmdline.rs    |  2 +-
7dd7e2
 src/install.rs    |  6 +++---
7dd7e2
 src/s390x/dasd.rs | 15 +++++++++++----
7dd7e2
 4 files changed, 43 insertions(+), 10 deletions(-)
7dd7e2
7dd7e2
diff --git a/src/blockdev.rs b/src/blockdev.rs
7dd7e2
index 90c6bee..df8e10a 100644
7dd7e2
--- a/src/blockdev.rs
7dd7e2
+++ b/src/blockdev.rs
7dd7e2
@@ -970,10 +970,36 @@ pub fn detect_formatted_sector_size(buf: &[u8]) -> Option<NonZeroU32> {
7dd7e2
 }
7dd7e2
 
7dd7e2
 /// Checks if underlying device is IBM DASD disk
7dd7e2
-pub fn is_dasd(device: &str) -> Result<bool> {
7dd7e2
+pub fn is_dasd(device: &str, fd: Option<&mut File>) -> Result<bool> {
7dd7e2
     let target =
7dd7e2
         canonicalize(device).with_context(|| format!("getting absolute path to {}", device))?;
7dd7e2
-    Ok(target.to_string_lossy().starts_with("/dev/dasd"))
7dd7e2
+    if target.to_string_lossy().starts_with("/dev/dasd") {
7dd7e2
+        return Ok(true);
7dd7e2
+    }
7dd7e2
+    let read_magic = |device: &str, disk: &mut File| -> Result<[u8; 4]> {
7dd7e2
+        let offset = disk
7dd7e2
+            .seek(SeekFrom::Current(0))
7dd7e2
+            .with_context(|| format!("saving offset {}", device))?;
7dd7e2
+        disk.seek(SeekFrom::Start(8194))
7dd7e2
+            .with_context(|| format!("seeking {}", device))?;
7dd7e2
+        let mut lbl = [0u8; 4];
7dd7e2
+        disk.read_exact(&mut lbl)
7dd7e2
+            .with_context(|| format!("reading label {}", device))?;
7dd7e2
+        disk.seek(SeekFrom::Start(offset))
7dd7e2
+            .with_context(|| format!("restoring offset {}", device))?;
7dd7e2
+        Ok(lbl)
7dd7e2
+    };
7dd7e2
+    if target.to_string_lossy().starts_with("/dev/vd") {
7dd7e2
+        let cdl_magic = [0xd3, 0xf1, 0xe5, 0xd6];
7dd7e2
+        let lbl = if let Some(t) = fd {
7dd7e2
+            read_magic(device, t)?
7dd7e2
+        } else {
7dd7e2
+            let mut disk = File::open(device).with_context(|| format!("opening {}", device))?;
7dd7e2
+            read_magic(device, &mut disk)?
7dd7e2
+        };
7dd7e2
+        return Ok(cdl_magic == lbl);
7dd7e2
+    }
7dd7e2
+    Ok(false)
7dd7e2
 }
7dd7e2
 
7dd7e2
 // create unsafe ioctl wrappers
7dd7e2
diff --git a/src/cmdline.rs b/src/cmdline.rs
7dd7e2
index db3d1d0..53b8179 100644
7dd7e2
--- a/src/cmdline.rs
7dd7e2
+++ b/src/cmdline.rs
7dd7e2
@@ -853,7 +853,7 @@ fn parse_install(matches: &ArgMatches) -> Result<Config> {
7dd7e2
     // it changes to the recommended 4096
7dd7e2
     // https://bugzilla.redhat.com/show_bug.cgi?id=1905159
7dd7e2
     #[allow(clippy::match_bool, clippy::match_single_binding)]
7dd7e2
-    let sector_size = match is_dasd(&device)
7dd7e2
+    let sector_size = match is_dasd(&device, None)
7dd7e2
         .with_context(|| format!("checking whether {} is an IBM DASD disk", device))?
7dd7e2
     {
7dd7e2
         #[cfg(target_arch = "s390x")]
7dd7e2
diff --git a/src/install.rs b/src/install.rs
7dd7e2
index baa3880..20d1f41 100644
7dd7e2
--- a/src/install.rs
7dd7e2
+++ b/src/install.rs
7dd7e2
@@ -47,7 +47,7 @@ pub fn install(config: &InstallConfig) -> Result<()> {
7dd7e2
 
7dd7e2
     #[cfg(target_arch = "s390x")]
7dd7e2
     {
7dd7e2
-        if is_dasd(&config.device)? {
7dd7e2
+        if is_dasd(&config.device, None)? {
7dd7e2
             if !config.save_partitions.is_empty() {
7dd7e2
                 // The user requested partition saving, but SavedPartitions
7dd7e2
                 // doesn't understand DASD VTOCs and won't find any partitions
7dd7e2
@@ -156,7 +156,7 @@ fn write_disk(
7dd7e2
 
7dd7e2
     // copy the image
7dd7e2
     #[allow(clippy::match_bool, clippy::match_single_binding)]
7dd7e2
-    let image_copy = match is_dasd(&config.device)? {
7dd7e2
+    let image_copy = match is_dasd(&config.device, Some(dest))? {
7dd7e2
         #[cfg(target_arch = "s390x")]
7dd7e2
         true => s390x::image_copy_s390x,
7dd7e2
         _ => image_copy_default,
7dd7e2
@@ -527,7 +527,7 @@ fn reset_partition_table(
7dd7e2
 ) -> Result<()> {
7dd7e2
     eprintln!("Resetting partition table");
7dd7e2
 
7dd7e2
-    if is_dasd(&config.device)? {
7dd7e2
+    if is_dasd(&config.device, Some(dest))? {
7dd7e2
         // Don't write out a GPT, since the backup GPT may overwrite
7dd7e2
         // something we're not allowed to touch.  Just clear the first MiB
7dd7e2
         // of disk.
7dd7e2
diff --git a/src/s390x/dasd.rs b/src/s390x/dasd.rs
7dd7e2
index 7145071..b7dea78 100644
7dd7e2
--- a/src/s390x/dasd.rs
7dd7e2
+++ b/src/s390x/dasd.rs
7dd7e2
@@ -35,13 +35,15 @@ pub(crate) struct Range {
7dd7e2
     pub length: u64,
7dd7e2
 }
7dd7e2
 
7dd7e2
-/// There are 2 types of DASD devices:
7dd7e2
+/// There are 3 types of DASD devices:
7dd7e2
 ///   - ECKD (Extended Count Key Data) - is regular DASD of type 3390
7dd7e2
 ///   - FBA (Fixed Block Access) - is used for emulated device that represents a real SCSI device
7dd7e2
+///   - Virt - ECKD on LPAR/zKVM as virtio-device
7dd7e2
 /// Only ECKD disks require `dasdfmt, fdasd` linux tools to be configured.
7dd7e2
 enum DasdType {
7dd7e2
     Eckd,
7dd7e2
     Fba,
7dd7e2
+    Virt,
7dd7e2
 }
7dd7e2
 
7dd7e2
 fn get_dasd_type<P: AsRef<Path>>(device: P) -> Result<DasdType> {
7dd7e2
@@ -53,6 +55,9 @@ fn get_dasd_type<P: AsRef<Path>>(device: P) -> Result<DasdType> {
7dd7e2
         .with_context(|| format!("getting name of {}", device.display()))?
7dd7e2
         .to_string_lossy()
7dd7e2
         .to_string();
7dd7e2
+    if device.starts_with("vd") {
7dd7e2
+        return Ok(DasdType::Virt);
7dd7e2
+    }
7dd7e2
     let devtype_path = format!("/sys/class/block/{}/device/devtype", device);
7dd7e2
     let devtype_str = std::fs::read_to_string(&devtype_path)
7dd7e2
         .with_context(|| format!("reading {}", devtype_path))?;
7dd7e2
@@ -66,7 +71,7 @@ fn get_dasd_type<P: AsRef<Path>>(device: P) -> Result<DasdType> {
7dd7e2
 pub fn prepare_dasd(dasd: &str) -> Result<()> {
7dd7e2
     match get_dasd_type(dasd)? {
7dd7e2
         DasdType::Eckd => eckd_prepare(dasd),
7dd7e2
-        DasdType::Fba => Ok(()),
7dd7e2
+        DasdType::Fba | DasdType::Virt => Ok(()),
7dd7e2
     }
7dd7e2
 }
7dd7e2
 
7dd7e2
@@ -75,7 +80,7 @@ pub fn prepare_dasd(dasd: &str) -> Result<()> {
7dd7e2
 pub fn dasd_try_get_sector_size(dasd: &str) -> Result<Option<NonZeroU32>> {
7dd7e2
     match get_dasd_type(dasd)? {
7dd7e2
         DasdType::Eckd => eckd_try_get_sector_size(dasd),
7dd7e2
-        DasdType::Fba => Ok(None),
7dd7e2
+        DasdType::Fba | DasdType::Virt => Ok(None),
7dd7e2
     }
7dd7e2
 }
7dd7e2
 
7dd7e2
@@ -87,8 +92,10 @@ pub fn image_copy_s390x(
7dd7e2
     _saved: Option<&SavedPartitions>,
7dd7e2
 ) -> Result<()> {
7dd7e2
     let ranges = match get_dasd_type(dest_path)? {
7dd7e2
-        DasdType::Eckd => eckd_make_partitions(&dest_path.to_string_lossy(), dest_file, first_mb)?,
7dd7e2
         DasdType::Fba => fba_make_partitions(&dest_path.to_string_lossy(), dest_file, first_mb)?,
7dd7e2
+        DasdType::Eckd | DasdType::Virt => {
7dd7e2
+            eckd_make_partitions(&dest_path.to_string_lossy(), dest_file, first_mb)?
7dd7e2
+        }
7dd7e2
     };
7dd7e2
 
7dd7e2
     // copy each partition
7dd7e2
-- 
7dd7e2
2.31.1
7dd7e2