From 1814aab2c54922c0052987b5b9eacf39ee8fb703 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 10 Oct 2025 07:59:28 +0000 Subject: [PATCH] cvm: Add XFS support --- docs/security-guide/cvm-boundaries.md | 2 +- dstack-util/src/system_setup.rs | 74 ++++++++++++++++++++++++++- vmm/src/console.html | 4 +- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/docs/security-guide/cvm-boundaries.md b/docs/security-guide/cvm-boundaries.md index 3eeb29ed..75630873 100644 --- a/docs/security-guide/cvm-boundaries.md +++ b/docs/security-guide/cvm-boundaries.md @@ -41,7 +41,7 @@ This is the main configuration file for the application in JSON format: | secure_time | 0.5.0 | boolean | Whether secure time is enabled | | pre_launch_script | 0.4.0 | string | Prelaunch bash script that runs before execute `docker compose up` | | init_script | 0.5.5 | string | Bash script that executed prior to dockerd startup | -| storage_fs | 0.5.5 | string | Filesystem type for the data disk of the CVM. Supported values: "zfs", "ext4". default to "zfs". **ZFS:** Ensures filesystem integrity with built-in data protection features. **ext4:** Provides better performance for database applications with lower overhead and faster I/O operations, but no strong integrity protection. | +| storage_fs | 0.5.5 | string | Filesystem type for the data disk of the CVM. Supported values: "zfs", "ext4", "xfs". default to "zfs". **ZFS:** Ensures filesystem integrity with built-in data protection features. **ext4:** Provides better performance for database applications with lower overhead and faster I/O operations, but no strong integrity protection. **xfs:** Scales well for large volumes and high-concurrency workloads | | swap_size | 0.5.5 | string/integer | The linux swap size. default to 0. Can be in byte or human-readable format (e.g., "1G", "256M"). | diff --git a/dstack-util/src/system_setup.rs b/dstack-util/src/system_setup.rs index d9207752..b6a8932a 100644 --- a/dstack-util/src/system_setup.rs +++ b/dstack-util/src/system_setup.rs @@ -94,6 +94,7 @@ enum FsType { #[default] Zfs, Ext4, + Xfs, } impl Display for FsType { @@ -101,6 +102,7 @@ impl Display for FsType { match self { FsType::Zfs => write!(f, "zfs"), FsType::Ext4 => write!(f, "ext4"), + FsType::Xfs => write!(f, "xfs"), } } } @@ -111,7 +113,8 @@ impl FromStr for FsType { match s.to_lowercase().as_str() { "zfs" => Ok(FsType::Zfs), "ext4" => Ok(FsType::Ext4), - _ => bail!("Invalid filesystem type: {s}, supported types: zfs, ext4"), + "xfs" => Ok(FsType::Xfs), + _ => bail!("Invalid filesystem type: {s}, supported types: zfs, ext4, xfs"), } } } @@ -691,7 +694,7 @@ impl<'a> Stage0<'a> { async fn setup_swap(&self, swap_size: u64, opts: &DstackOptions) -> Result<()> { match opts.storage_fs { FsType::Zfs => self.setup_swap_zvol(swap_size).await, - FsType::Ext4 => self.setup_swapfile(swap_size).await, + FsType::Ext4 | FsType::Xfs => self.setup_swapfile(swap_size).await, } } @@ -814,6 +817,15 @@ impl<'a> Stage0<'a> { } .context("Failed to create ext4 filesystem")?; } + FsType::Xfs => { + info!("Creating xfs filesystem"); + cmd! { + mkfs.xfs -f $fs_dev; + } + .context("Failed to create xfs filesystem")?; + Self::mount_xfs(&fs_dev, mount_point, false) + .context("Failed to mount newly created xfs filesystem")?; + } } } else { self.vmm @@ -843,6 +855,10 @@ impl<'a> Stage0<'a> { Self::mount_e2fs(&fs_dev, mount_point) .context("Failed to mount ext4 filesystem")?; } + FsType::Xfs => { + Self::mount_xfs(&fs_dev, mount_point, true) + .context("Failed to mount xfs filesystem")?; + } } } Ok(()) @@ -886,6 +902,60 @@ impl<'a> Stage0<'a> { Ok(()) } + fn mount_xfs( + dev: &impl AsRef, + mount_point: &impl AsRef, + run_check: bool, + ) -> Result<()> { + let dev = dev.as_ref(); + let mount_point = mount_point.as_ref(); + if run_check { + info!("Checking filesystem"); + + let repair_status = Command::new("xfs_repair") + .arg("-n") + .arg(dev) + .status() + .with_context(|| format!("Failed to run xfs_repair on {}", dev.display()))?; + + match repair_status.code() { + Some(0) => {} + Some(1) => { + warn!( + "xfs_repair reported issues on {}, continuing without modification", + dev.display() + ); + } + Some(code) => { + bail!( + "xfs_repair exited with status {code} while checking {}", + dev.display() + ); + } + None => { + bail!( + "xfs_repair terminated by signal while checking {}", + dev.display() + ); + } + } + } + + cmd! { + info "Mounting filesystem"; + mount $dev $mount_point; + } + .context("Failed to mount xfs filesystem")?; + + cmd! { + info "Growing filesystem if needed"; + xfs_growfs $mount_point; + } + .context("Failed to grow xfs filesystem")?; + + Ok(()) + } + fn luks_setup(&self, disk_crypt_key: &str, name: &str) -> Result<()> { let root_hd = &self.args.device; let sector_offset = PAYLOAD_OFFSET / 512; diff --git a/vmm/src/console.html b/vmm/src/console.html index c07a6f4e..b46fb53a 100644 --- a/vmm/src/console.html +++ b/vmm/src/console.html @@ -737,7 +737,8 @@

Deploy a new instance

ZFS: Ensures filesystem integrity with built-in data protection features.

ext4: Provides better performance for database applications - with lower overhead and faster I/O operations. + with lower overhead and faster I/O operations.

+ XFS: Optimized for scaling large volumes and parallel I/O.
@@ -745,6 +746,7 @@

Deploy a new instance

+