]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Diskmanage.pm
diskmanage: don't set usage for unused partitions
[pve-storage.git] / PVE / Diskmanage.pm
index 55da2e5f285a34b70c5c9e27fa8220866efb8710..c896c5ab3a0e26a2b036e9d8bff6c89cb2e24066 100644 (file)
@@ -20,6 +20,12 @@ my $PVS = "/sbin/pvs";
 my $LVS = "/sbin/lvs";
 my $LSBLK = "/bin/lsblk";
 
+my sub strip_dev :prototype($) {
+    my ($devpath) = @_;
+    $devpath =~ s|^/dev/||;
+    return $devpath;
+}
+
 sub check_bin {
     my ($path) = @_;
     return -x $path;
@@ -251,7 +257,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 = {
@@ -327,7 +333,7 @@ sub get_udev_info {
     warn $@ if $@;
     return undef if !$info;
 
-    return undef if $info !~ m/^E: DEVTYPE=disk$/m;
+    return undef if $info !~ m/^E: DEVTYPE=(disk|partition)$/m;
     return undef if $info =~ m/^E: ID_CDROM/m;
 
     # we use this, because some disks are not simply in /dev
@@ -518,6 +524,14 @@ sub get_disks {
        # we get cciss/c0d0 but need cciss!c0d0
        $_ =~ s|cciss/|cciss!| for @$disks;
 
+       if ($include_partitions) {
+           # Proper blockdevice is needed for the regex, use parent for partitions.
+           for my $disk ($disks->@*) {
+               next if !is_partition("/dev/$disk");
+               $disk = strip_dev(get_blockdev("/dev/$disk"));
+           }
+       }
+
        $disk_regex = "(?:" . join('|', @$disks) . ")";
     }
 
@@ -647,7 +661,7 @@ sub get_disks {
            # for devices, this check is done explicitly later
            return 'Device Mapper' if !dir_is_empty("$sysdir/holders");
 
-           return 'partition';
+           return; # unused partition
        };
 
        my $collect_ceph_info = sub {
@@ -716,7 +730,6 @@ sub get_disks {
        my $used = $determine_usage->($devpath, $sysdir, 0);
        if (!$include_partitions) {
            foreach my $part (sort keys %{$partitions}) {
-               next if $partitions->{$part}->{used} eq 'partition';
                $used //= $partitions->{$part}->{used};
            }
        } else {
@@ -794,11 +807,17 @@ 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;
 }
 
+sub is_partition {
+    my ($dev_path) = @_;
+
+    return defined(eval { get_partnum($dev_path) });
+}
+
 sub locked_disk_action {
     my ($sub) = @_;
     my $res = PVE::Tools::lock_file('/run/lock/pve-diskmanage.lck', undef, $sub);
@@ -836,7 +855,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) = @_;
@@ -847,12 +866,6 @@ sub append_partition {
     return $partition;
 }
 
-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().
@@ -895,7 +908,25 @@ sub is_mounted {
     return $found;
 }
 
+# Currently only supports GPT-partitioned disks.
+sub change_parttype {
+    my ($partpath, $parttype) = @_;
+
+    my $err = "unable to change partition type for $partpath";
+
+    my $partnum = get_partnum($partpath);
+    my $blockdev = get_blockdev($partpath);
+    my $dev = strip_dev($blockdev);
+
+    my $info = get_disks($dev, 1);
+    die "$err - unable to get disk info for '$blockdev'\n" if !defined($info->{$dev});
+    die "$err - disk '$blockdev' is not GPT partitioned\n" if !$info->{$dev}->{gpt};
+
+    run_command(['sgdisk', "-t${partnum}:${parttype}", $blockdev], errmsg => $err);
+}
+
 # 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'.
 # Expected to be called with a result of verify_blockdev_path().
 sub wipe_blockdev {
     my ($devpath) = @_;
@@ -915,7 +946,7 @@ sub wipe_blockdev {
        push $to_wipe->@*, "/dev/${part}" if -b "/dev/${part}";
     });
 
-    if (scalar($to_wipe->$#*) > 0) {
+    if (scalar($to_wipe->@*) > 0) {
        print "found child partitions to wipe: ". join(', ', $to_wipe->@*) ."\n";
     }
     push $to_wipe->@*, $devpath; # put actual device last
@@ -928,6 +959,11 @@ sub wipe_blockdev {
        ['dd', 'if=/dev/zero', "of=${devpath}", 'bs=1M', 'conv=fdatasync', "count=${count}"],
        errmsg => "error wiping '${devpath}'",
     );
+
+    if (is_partition($devpath)) {
+       eval { change_parttype($devpath, '8300'); };
+       warn $@ if $@;
+    }
 }
 
 1;