[pve-devel] [PATCH manager] Fix #2051: sub wipe_disks wipes partitions too

Thomas Lamprecht t.lamprecht at proxmox.com
Mon Jan 21 19:15:52 CET 2019


For the commit message try to avoid mentioning perl specifics if it's not
addressing a perl specific issue.. I see that you touch wipe_disks in the
diff, for the commit message itself OK, but not in the subject.
Maybe something like:

Fix #2051: preserve DB/WAL possible still in use when destroying OSDs

On 1/21/19 1:44 PM, Alwin Antreich wrote:
> 'pveceph osd destroy <num> --cleanup'
> 
> When executing the command above, all disks associated with the OSD are
> at the moment wiped with dd (incl. separate disks with DB/WAL).
> 
> The patch adds the ability to 'wipe_disks' to wipe the partition instead
> of the whole disk. This preserves the sparate DB/WAL disks.

s/sparate/separate/

> 
> Signed-off-by: Alwin Antreich <a.antreich at proxmox.com>
> ---
>  PVE/API2/Ceph/OSD.pm |  8 +++-----
>  PVE/Ceph/Tools.pm    | 20 ++++++++++++++++----
>  2 files changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/PVE/API2/Ceph/OSD.pm b/PVE/API2/Ceph/OSD.pm
> index b4dc277e..939958d9 100644
> --- a/PVE/API2/Ceph/OSD.pm
> +++ b/PVE/API2/Ceph/OSD.pm
> @@ -1,5 +1,6 @@
>  package PVE::API2::Ceph::OSD;
>  
> +
>  use strict;
>  use warnings;
>  
> @@ -394,19 +395,18 @@ __PACKAGE__->register_method ({
>  	    # try to unmount from standard mount point
>  	    my $mountpoint = "/var/lib/ceph/osd/ceph-$osdid";
>  
> -	    my $disks_to_wipe = {};
>  	    my $remove_partition = sub {
>  		my ($part) = @_;
>  
>  		return if !$part || (! -b $part );
> +		($part) = $part =~ m|^(/.+)|; # untaint $part

maybe to the untaint below where we itterate over proc/mounts and check already for
/dev:
next if $dev !~ m|^/dev/|;
(one could add a capture group and just set $dev to $1 afterwards.)

>  		my $partnum = PVE::Diskmanage::get_partnum($part);
>  		my $devpath = PVE::Diskmanage::get_blockdev($part);
>  
> +		PVE::Ceph::Tools::wipe_disks($part);
>  		print "remove partition $part (disk '${devpath}', partnum $partnum)\n";
>  		eval { run_command(['/sbin/sgdisk', '-d', $partnum, "${devpath}"]); };
>  		warn $@ if $@;
> -
> -		$disks_to_wipe->{$devpath} = 1;
>  	    };
>  
>  	    my $partitions_to_remove = [];
> @@ -443,8 +443,6 @@ __PACKAGE__->register_method ({
>  		foreach my $part (@$partitions_to_remove) {
>  		    $remove_partition->($part);
>  		}
> -
> -		PVE::Ceph::Tools::wipe_disks(keys %$disks_to_wipe);
>  	    }
>  	};
>  
> diff --git a/PVE/Ceph/Tools.pm b/PVE/Ceph/Tools.pm
> index 0ada98cf..f0a3cb54 100644
> --- a/PVE/Ceph/Tools.pm
> +++ b/PVE/Ceph/Tools.pm
> @@ -232,11 +232,23 @@ sub systemd_managed {
>  sub wipe_disks {
>      my (@devs) = @_;
>  
> -    my @wipe_cmd = qw(/bin/dd if=/dev/zero bs=1M count=200 conv=fdatasync);
> +    my @wipe_cmd = qw(/bin/dd if=/dev/zero bs=1M conv=fdatasync);
> +    my $count = 200;
> +    my @blockdev = qw(/sbin/blockdev --getsize64);
> +    my $dev_size = 0;
> +
>      foreach my $devpath (@devs) {
> -        print "wipe disk: $devpath\n";
> -        eval { run_command([@wipe_cmd, "of=${devpath}"]) };
> -        warn $@ if $@;
> +	eval { run_command([@blockdev, "$devpath"],
> +	    outfunc => sub { $dev_size = shift; })};

this is really hard to read now... first break up the eval body into a newline,
as a starter, then I'd keep it a single line even if it needs more than 80 chars,
or at least keep "outfunc => sub {" on the first line.

Does reading "/sys/class/block/PARTITION/size" works too? Would sound a bit
saner/faster than spawing multiple processes for this...

> +	warn $@ if $@;
> +
> +	my $size = ($dev_size / 1024 / 1024);
> +	$count = $size if ($size lt $count);

why lt? we never use this, use <
Also, you do not reset the $count variable to 200 at loop start...
So if you have multiple @devs passed where the first is 100M big and the
second 150M you will wipe the full first one but only 100M from the second
one..

maybe do $count away completely and just do something like:
$size = ($size < 200) ? $size : 200; # we only need to wipe the first 200M

> +	push @wipe_cmd, "count=$count";

you add "count=$count" to the @wipe_cmd list _each_ iteration of this loop,
meaning that you'll get a failure from dd if more than one @devs is passed.

need to think a bit more about the general approach...

> +
> +	print "wipe disk/partition: $devpath\n";
> +	eval { run_command([@wipe_cmd, "of=${devpath}"]) };
> +	warn $@ if $@;
>      }
>  };
>  
> 





More information about the pve-devel mailing list