From: Markus Frank <m.frank@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v3 2/6] fix #3690: tools: add wipe_blockdev & change_parttype rust equivalent
Date: Tue, 28 Nov 2023 14:23:19 +0100 [thread overview]
Message-ID: <20231128132323.162721-3-m.frank@proxmox.com> (raw)
In-Reply-To: <20231128132323.162721-1-m.frank@proxmox.com>
The wipe_blockdev & change_parttype functions are similar to
PVE::Diskmanage's wipe_blockdev & change_parttype functions.
The partition_by_name & complete_partition_name functions are
modified disk_by_name & complete_disk_name functions for partitions.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
src/tools/disks/mod.rs | 125 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 124 insertions(+), 1 deletion(-)
diff --git a/src/tools/disks/mod.rs b/src/tools/disks/mod.rs
index 8b6d470b..beb8178b 100644
--- a/src/tools/disks/mod.rs
+++ b/src/tools/disks/mod.rs
@@ -16,10 +16,12 @@ use ::serde::{Deserialize, Serialize};
use proxmox_lang::error::io_err_other;
use proxmox_lang::{io_bail, io_format_err};
+use proxmox_rest_server::WorkerTask;
use proxmox_schema::api;
use proxmox_sys::linux::procfs::{mountinfo::Device, MountInfo};
+use proxmox_sys::task_log;
-use pbs_api_types::BLOCKDEVICE_NAME_REGEX;
+use pbs_api_types::{BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX, BLOCKDEVICE_NAME_REGEX};
mod zfs;
pub use zfs::*;
@@ -111,6 +113,12 @@ impl DiskManage {
self.disk_by_sys_path(syspath)
}
+ /// Get a `Disk` for a name in `/sys/class/block/<name>`.
+ pub fn partition_by_name(self: Arc<Self>, name: &str) -> io::Result<Disk> {
+ let syspath = format!("/sys/class/block/{}", name);
+ self.disk_by_sys_path(syspath)
+ }
+
/// Gather information about mounted disks:
fn mounted_devices(&self) -> Result<&HashSet<dev_t>, Error> {
self.mounted_devices
@@ -1056,6 +1064,105 @@ pub fn inititialize_gpt_disk(disk: &Disk, uuid: Option<&str>) -> Result<(), Erro
Ok(())
}
+/// Wipes all labels and the first 200 MiB of a disk/partition (or the whole if it is smaller).
+/// If called with a partition, also sets the partition type to 0x83 'Linux filesystem'.
+pub fn wipe_blockdev(disk: &Disk, worker: Arc<WorkerTask>) -> Result<(), Error> {
+ let disk_path = match disk.device_path() {
+ Some(path) => path,
+ None => bail!("disk {:?} has no node in /dev", disk.syspath()),
+ };
+ let disk_path_str = match disk_path.to_str() {
+ Some(path) => path,
+ None => bail!("disk {:?} could not transform into a str", disk.syspath()),
+ };
+
+ let mut is_partition = false;
+ for disk_info in get_lsblk_info()?.iter() {
+ if disk_info.path == disk_path_str && disk_info.partition_type.is_some() {
+ is_partition = true;
+ }
+ }
+
+ let mut to_wipe: Vec<PathBuf> = Vec::new();
+
+ let partitions_map = disk.partitions()?;
+ for part_disk in partitions_map.values() {
+ let part_path = match part_disk.device_path() {
+ Some(path) => path,
+ None => bail!("disk {:?} has no node in /dev", part_disk.syspath()),
+ };
+ to_wipe.push(part_path.to_path_buf());
+ }
+
+ to_wipe.push(disk_path.to_path_buf());
+
+ task_log!(worker, "Wiping block device {}", disk_path.display());
+
+ let mut wipefs_command = std::process::Command::new("wipefs");
+ wipefs_command.arg("--all").args(&to_wipe);
+
+ let wipefs_output = proxmox_sys::command::run_command(wipefs_command, None)?;
+ task_log!(worker, "wipefs output: {}", wipefs_output);
+
+ let size = disk.size().map(|size| size / 1024 / 1024)?;
+ let count = size.min(200);
+
+ let mut dd_command = std::process::Command::new("dd");
+ let mut of_path = OsString::from("of=");
+ of_path.push(disk_path);
+ let mut count_str = OsString::from("count=");
+ count_str.push(count.to_string());
+ let args = [
+ "if=/dev/zero".into(),
+ of_path,
+ "bs=1M".into(),
+ "conv=fdatasync".into(),
+ count_str.into(),
+ ];
+ dd_command.args(args);
+
+ let dd_output = proxmox_sys::command::run_command(dd_command, None)?;
+ task_log!(worker, "dd output: {}", dd_output);
+
+ if is_partition {
+ // set the partition type to 0x83 'Linux filesystem'
+ change_parttype(&disk, "8300", worker)?;
+ }
+
+ Ok(())
+}
+
+pub fn change_parttype(
+ part_disk: &Disk,
+ part_type: &str,
+ worker: Arc<WorkerTask>,
+) -> Result<(), Error> {
+ let part_path = match part_disk.device_path() {
+ Some(path) => path,
+ None => bail!("disk {:?} has no node in /dev", part_disk.syspath()),
+ };
+ if let Ok(stat) = nix::sys::stat::stat(part_path) {
+ let mut sgdisk_command = std::process::Command::new("sgdisk");
+ let major = unsafe { libc::major(stat.st_rdev) };
+ let minor = unsafe { libc::minor(stat.st_rdev) };
+ let partnum_path = &format!("/sys/dev/block/{}:{}/partition", major, minor);
+ let partnum: u32 = std::fs::read_to_string(partnum_path)?.trim_end().parse()?;
+ sgdisk_command.arg(&format!("-t{}:{}", partnum, part_type));
+ let part_disk_parent = match part_disk.parent() {
+ Some(disk) => disk,
+ None => bail!("disk {:?} has no node in /dev", part_disk.syspath()),
+ };
+ let part_disk_parent_path = match part_disk_parent.device_path() {
+ Some(path) => path,
+ None => bail!("disk {:?} has no node in /dev", part_disk.syspath()),
+ };
+ sgdisk_command.arg(part_disk_parent_path);
+ let sgdisk_output = proxmox_sys::command::run_command(sgdisk_command, None)?;
+ task_log!(worker, "sgdisk output: {}", sgdisk_output);
+ }
+ Ok(())
+}
+
/// Create a single linux partition using the whole available space
pub fn create_single_linux_partition(disk: &Disk) -> Result<Disk, Error> {
let disk_path = match disk.device_path() {
@@ -1136,6 +1243,22 @@ pub fn complete_disk_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<S
.collect()
}
+/// Block device partition name completion helper
+pub fn complete_partition_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
+ let dir = match proxmox_sys::fs::scan_subdir(
+ libc::AT_FDCWD,
+ "/sys/class/block",
+ &BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX,
+ ) {
+ Ok(dir) => dir,
+ Err(_) => return vec![],
+ };
+
+ dir.flatten()
+ .map(|item| item.file_name().to_str().unwrap().to_string())
+ .collect()
+}
+
/// Read the FS UUID (parse blkid output)
///
/// Note: Calling blkid is more reliable than using the udev ID_FS_UUID property.
--
2.39.2
next prev parent reply other threads:[~2023-11-28 13:24 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-28 13:23 [pbs-devel] [PATCH proxmox-backup v3 0/6] fix #3690: wipe disk Markus Frank
2023-11-28 13:23 ` [pbs-devel] [PATCH proxmox-backup v3 1/6] fix #3690: pbs_api_types: add regex, format & schema for partition names to pbs-api-types Markus Frank
2023-11-28 17:41 ` [pbs-devel] applied: " Thomas Lamprecht
2023-11-28 13:23 ` Markus Frank [this message]
2023-11-28 17:42 ` [pbs-devel] applied: [PATCH proxmox-backup v3 2/6] fix #3690: tools: add wipe_blockdev & change_parttype rust equivalent Thomas Lamprecht
2023-11-28 13:23 ` [pbs-devel] [PATCH proxmox-backup v3 3/6] fix #3690: api: add function wipe_disk Markus Frank
2023-11-28 17:42 ` [pbs-devel] applied: " Thomas Lamprecht
2023-11-28 13:23 ` [pbs-devel] [PATCH proxmox-backup v3 4/6] fix #3690: cli: " Markus Frank
2023-11-28 17:43 ` [pbs-devel] applied: " Thomas Lamprecht
2023-11-28 13:23 ` [pbs-devel] [PATCH proxmox-backup v3 5/6] fix #3690: ui: enable wipe disk in StorageAndDisks Markus Frank
2023-11-28 17:44 ` [pbs-devel] applied: " Thomas Lamprecht
2023-11-28 13:23 ` [pbs-devel] [PATCH proxmox-backup v3 6/6] tools: prohibit disk wipe of EFI partition Markus Frank
2023-11-28 17:48 ` Thomas Lamprecht
2023-11-28 21:56 ` Roland
2023-11-28 14:20 ` [pbs-devel] [PATCH proxmox-backup v3 0/6] fix #3690: wipe disk Lukas Wagner
2023-11-28 14:38 ` Max Carrara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231128132323.162721-3-m.frank@proxmox.com \
--to=m.frank@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.