[pve-devel] [PATCH v3 storage 1/4] move SMART error handling into get_disks

Fabian Gr├╝nbichler f.gruenbichler at proxmox.com
Wed Sep 28 13:42:22 CEST 2016


because we never ever want to die in get_disks because of a
single disk, but the nodes/xyz/disks/smart API path is
allowed to fail if a disk device is unsupported by smartctl
or something else goes wrong.
---
 PVE/API2/Disks.pm |  2 ++
 PVE/Diskmanage.pm | 69 ++++++++++++++++++++++++++-----------------------------
 2 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/PVE/API2/Disks.pm b/PVE/API2/Disks.pm
index 279d351..d7030f8 100644
--- a/PVE/API2/Disks.pm
+++ b/PVE/API2/Disks.pm
@@ -138,6 +138,8 @@ __PACKAGE__->register_method ({
 	    $result = PVE::Diskmanage::get_smart_data($disk);
 	}
 
+	$result->{health} = 'UNKOWN' if !defined $result->{health};
+
 	return $result;
     }});
 
diff --git a/PVE/Diskmanage.pm b/PVE/Diskmanage.pm
index bee5d99..5909d73 100644
--- a/PVE/Diskmanage.pm
+++ b/PVE/Diskmanage.pm
@@ -110,7 +110,6 @@ sub get_smart_data {
     if ((defined($returncode) && ($returncode & 0b00000011)) || $err) {
 	die "Error getting S.M.A.R.T. data: Exit code: $returncode\n";
     }
-    $smartdata->{health} = 'UNKOWN' if !defined $smartdata->{health};
     return $smartdata;
 }
 
@@ -119,22 +118,19 @@ sub get_smart_health {
 
     return "NOT A DEVICE" if !assert_blockdev($disk, 1);
 
-    my $message = "UNKOWN";
+    my $message;
 
-    eval {
-	run_command([$SMARTCTL, '-H', $disk], noerr => 1, outfunc => sub {
-	    my ($line) = @_;
+    run_command([$SMARTCTL, '-H', $disk], noerr => 1, outfunc => sub {
+	my ($line) = @_;
 
-	    if ($line =~ m/test result: (.*)$/) {
-		$message = $1;
-	    } elsif ($line =~ m/open device: (.*) failed: (.*)$/) {
-		$message = "FAILED TO OPEN";
-	    } elsif ($line =~ m/^SMART Disabled/) {
-		$message = "SMART DISABLED";
-	    }
-	});
-    };
-    # we ignore errors here because by default we want to return UNKNOWN
+	if ($line =~ m/test result: (.*)$/) {
+	    $message = $1;
+	} elsif ($line =~ m/open device: (.*) failed: (.*)$/) {
+	    $message = "FAILED TO OPEN";
+	} elsif ($line =~ m/^SMART Disabled/) {
+	    $message = "SMART DISABLED";
+	}
+    });
 
     return $message;
 }
@@ -366,29 +362,30 @@ sub get_disks {
 	    }
 	}
 
-	my $health;
+	my $health = 'UNKNOWN';
 	my $wearout;
-	if ($type eq 'ssd' && !defined($disk)) {
-	    # if we have an ssd we try to get the wearout indicator
-	    my $smartdata = get_smart_data($devpath);
-	    $health = $smartdata->{health};
-	    foreach my $attr (@{$smartdata->{attributes}}) {
-		# ID 233 is media wearout indicator on intel and sandisk
-		# ID 177 is media wearout indicator on samsung
-		next if ($attr->{id} != 233 && $attr->{id} != 177);
-		next if ($attr->{name} !~ m/wear/i);
-		$wearout = $attr->{value};
-
-		# prefer the 233 value
-		last if ($attr->{id} == 233);
+	eval {
+	    if ($type eq 'ssd' && !defined($disk)) {
+		# if we have an ssd we try to get the wearout indicator
+		$wearout = 'N/A';
+		my $smartdata = get_smart_data($devpath);
+		$health = $smartdata->{health};
+		foreach my $attr (@{$smartdata->{attributes}}) {
+		    # ID 233 is media wearout indicator on intel and sandisk
+		    # ID 177 is media wearout indicator on samsung
+		    next if ($attr->{id} != 233 && $attr->{id} != 177);
+		    next if ($attr->{name} !~ m/wear/i);
+		    $wearout = $attr->{value};
+
+		    # prefer the 233 value
+		    last if ($attr->{id} == 233);
+		}
+	    } elsif (!defined($disk)) {
+		# we do not need smart data if we check a single disk
+		# because this functionality is only for disk_is_used
+		$health = get_smart_health($devpath) if !defined($disk);
 	    }
-
-	    $wearout = 'N/A' if !defined($wearout);
-	} elsif (!defined($disk)) {
-	    # we do not need smart data if we check a single disk
-	    # because this functionality is only for disk_is_used
-	    $health = get_smart_health($devpath) if !defined($disk);
-	}
+	};
 
 	my $used;
 
-- 
2.1.4




More information about the pve-devel mailing list