X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FDiskmanage.pm;h=10e12184298051d670def31b610cacce83992fa8;hb=1c1589e60da9c2a5d47e5cafbd50fd13f6cbd3c8;hp=612d97648fbbd76401a0891c73ba6be6ad86c22a;hpb=262ad7a92e91c9d0ed883347ae4fa475744293aa;p=pve-storage.git diff --git a/PVE/Diskmanage.pm b/PVE/Diskmanage.pm index 612d976..10e1218 100644 --- a/PVE/Diskmanage.pm +++ b/PVE/Diskmanage.pm @@ -22,7 +22,6 @@ my $LSBLK = "/bin/lsblk"; sub check_bin { my ($path) = @_; - return -x $path; } @@ -252,7 +251,7 @@ sub get_lvm_devices { }; # if something goes wrong, we do not want - # to give up, but indicate an error has occured + # to give up, but indicate an error has occurred warn "$@\n" if $@; my $uuids = { @@ -481,10 +480,7 @@ my sub is_ssdlike { return $type eq 'ssd' || $type eq 'nvme'; } -sub get_disks { - my ($disks, $nosmart, $include_partitions) = @_; - my $disklist = {}; - +sub mounted_blockdevs { my $mounted = {}; my $mounts = PVE::ProcFSTools::parse_proc_mounts(); @@ -494,6 +490,15 @@ sub get_disks { $mounted->{abs_path($mount->[0])} = $mount->[1]; }; + return $mounted; +} + +sub get_disks { + my ($disks, $nosmart, $include_partitions) = @_; + my $disklist = {}; + + my $mounted = mounted_blockdevs(); + my $lsblk_info = get_lsblk_info(); my $journalhash = get_ceph_journals($lsblk_info); @@ -789,7 +794,7 @@ sub get_blockdev { die "No valid block device\n" if index($dev, $block_dev) == -1; $block_dev = "/dev/$block_dev"; - die "Block device does not exsists\n" if !(-b $block_dev); + die "Block device does not exists\n" if !(-b $block_dev); return $block_dev; } @@ -831,7 +836,7 @@ sub append_partition { my $partition; - # loop again to detect the real partiton device which does not always follow + # loop again to detect the real partition device which does not always follow # a strict $devname$partition scheme like /dev/nvme0n1 -> /dev/nvme0n1p1 dir_glob_foreach("/sys/block/$devname", qr/\Q$devname\E.*$newpartid/, sub { my ($part) = @_; @@ -842,14 +847,58 @@ sub append_partition { return $partition; } -# Wipes all labels and the first 200 MiB of a disk/partition (or the whole if it is smaller). +my sub strip_dev :prototype($) { + my ($devpath) = @_; + $devpath =~ s|^/dev/||; + return $devpath; +} + +# Check if a disk or any of its partitions has a holder. +# Can also be called with a partition. # Expected to be called with a result of verify_blockdev_path(). -sub wipe_blockdev { +sub has_holder { my ($devpath) = @_; - my $wipefs_cmd = ['wipefs', '--all', $devpath]; + my $dev = strip_dev($devpath); - my $dd_cmd = ['dd', 'if=/dev/zero', "of=${devpath}", 'bs=1M', 'conv=fdatasync']; + return $devpath if !dir_is_empty("/sys/class/block/${dev}/holders"); + + my $found; + dir_glob_foreach("/sys/block/${dev}", "${dev}.+", sub { + my ($part) = @_; + $found = "/dev/${part}" if !dir_is_empty("/sys/class/block/${part}/holders"); + }); + + return $found; +} + +# Basic check if a disk or any of its partitions is mounted. +# Can also be called with a partition. +# Expected to be called with a result of verify_blockdev_path(). +sub is_mounted { + my ($devpath) = @_; + + my $mounted = mounted_blockdevs(); + + return $devpath if $mounted->{$devpath}; + + my $dev = strip_dev($devpath); + + my $found; + dir_glob_foreach("/sys/block/${dev}", "${dev}.+", sub { + my ($part) = @_; + my $partpath = "/dev/${part}"; + + $found = $partpath if $mounted->{$partpath}; + }); + + return $found; +} + +# Wipes all labels and the first 200 MiB of a disk/partition (or the whole if it is smaller). +# Expected to be called with a result of verify_blockdev_path(). +sub wipe_blockdev { + my ($devpath) = @_; my $devname = basename($devpath); my $dev_size = PVE::Tools::file_get_contents("/sys/class/block/$devname/size"); @@ -860,12 +909,25 @@ sub wipe_blockdev { my $size = ($dev_size * 512 / 1024 / 1024); my $count = ($size < 200) ? $size : 200; - push @{$dd_cmd}, "count=${count}"; + my $to_wipe = []; + dir_glob_foreach("/sys/class/block/${devname}", "${devname}.+", sub { + my ($part) = @_; + push $to_wipe->@*, "/dev/${part}" if -b "/dev/${part}"; + }); + + if (scalar($to_wipe->@*) > 0) { + print "found child partitions to wipe: ". join(', ', $to_wipe->@*) ."\n"; + } + push $to_wipe->@*, $devpath; # put actual device last - print "wiping disk/partition: ${devpath}\n"; + print "wiping block device ${devpath}\n"; - run_command($wipefs_cmd, errmsg => "error wiping labels for '${devpath}'"); - run_command($dd_cmd, errmsg => "error wiping '${devpath}'"); + run_command(['wipefs', '--all', $to_wipe->@*], errmsg => "error wiping '${devpath}'"); + + run_command( + ['dd', 'if=/dev/zero', "of=${devpath}", 'bs=1M', 'conv=fdatasync', "count=${count}"], + errmsg => "error wiping '${devpath}'", + ); } 1;