* [PATCH] fix #7551: storage: normalize wearout detection using smartctl fields and types
@ 2026-11-09 10:56 piknew
0 siblings, 0 replies; only message in thread
From: piknew @ 2026-11-09 10:56 UTC (permalink / raw)
To: pve-devel
Some SSD models (such as Crucial MX500) report the SMART attribute 202
(Percent_Lifetime_Remain) where the VALUE field wraps around or acts
unreliably, but the RAW field accurately holds the wearout percentage.
Conversely, other drives like Samsung use attribute 173 (Wear_Leveling_Count)
as a remaining life indicator inside the VALUE field.
This patch refactors get_wear_leveling_info by introducing a flag mapping
for known registers. It ensures that wearout is computed natively as "used
percentage" based on the exact source (VALUE or RAW) and calculation type
(Lifetime_Used or Lifetime_Remaining). Additionally, it fixes the nvme
"Percentage Used" parser in get_smart_data to align with the normalized
wearout approach.
Signed-off-by: piknew <mparka@wp.pl>
---
src/PVE/Diskmanage.pm | 45 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/src/PVE/Diskmanage.pm b/src/PVE/Diskmanage.pm
index f519f10..4b5555e 100644
--- a/src/PVE/Diskmanage.pm
+++ b/src/PVE/Diskmanage.pm
@@ -172,7 +172,7 @@ sub get_smart_data {
if ($line =~
m/Percentage Used(?: endurance indicator)?:\s*(\d+(?:\.\d+)?)\%/i
) {
- $smartdata->{wearout} = 100 - $1;
+ $smartdata->{wearout} = $1;
}
} elsif ($line =~ m/SMART Disabled/) {
$smartdata->{health} = "SMART Disabled";
@@ -466,12 +466,53 @@ sub get_wear_leveling_info {
"Perc_Rated_Life_Used",
);
+ # The flags, which determines:
+ # TYPE: if value is treated as "wear level" (Lifetime_Used) or "remaining life" (Lifetime_Remaining, default)
+ # SOURCE: which field in smart data is sourcing the value: value (VALUE, default) or raw (RAW)
+ my $wearoutregisterflags = {
+ # This is usage for SAMSUNG MZ7LN256HAJQ-000H1 (VALUE and Lifetime_Remaining shall be utilized):
+ # 173 Wear_Leveling_Count 0x0032 094 094 005 Old_age Always - 72 (this is 6% of usage for SAMSUNG MZ7LN256HAJQ-000H1)
+ "Wear_Leveling_Count" => {
+ "TYPE" => "Lifetime_Remaining",
+ "SOURCE" => "VALUE"
+ },
+ # These are usages for CRUCIALs CT250MX500SSD1 and CT500MX500SSD1 (RAW and Lifetime_Used shall be utilized):
+ # 202 Percent_Lifetime_Remain 0x0030 053 053 001 Old_age Offline - 47 (this is 47% of usage for CRUCIAL CT250MX500SSD1)
+ # 202 Percent_Lifetime_Remain 0x0030 047 047 001 Old_age Offline - 53 (this is 53% of usage for CRUCIAL CT250MX500SSD1)
+ # 202 Percent_Lifetime_Remain 0x0030 224 224 001 Old_age Offline - 132 (this is 132% of usage for CRUCIAL CT500MX500SSD1)
+ # 202 Percent_Lifetime_Remain 0x0030 253 253 001 Old_age Offline - 103 (this is 103% of usage for CRUCIAL CT250MX500SSD1)
+ "Percent_Lifetime_Remain" => {
+ "TYPE" => "Lifetime_Used",
+ "SOURCE" => "RAW"
+ },
+ # if attribute is not defined then fallback into defaults is provided:
+ "default" => {
+ "TYPE" => "Lifetime_Remaining",
+ "SOURCE" => "VALUE"
+ }
+ };
+
# Search for S.M.A.R.T. attributes for known register
foreach my $register (@wearoutregisters) {
last if defined $wearout;
+ my $flags = $wearoutregisterflags->{"default"};
+ if (defined($wearoutregisterflags->{$register})) {
+ $flags = $wearoutregisterflags->{$register}
+ }
foreach my $attr (@$attributes) {
next if $attr->{name} !~ m/$register/;
- $wearout = $attr->{value};
+ if ($flags->{"SOURCE"} eq "VALUE") {
+ $wearout = $attr->{value};
+ } elsif ($flags->{"SOURCE"} eq "RAW") {
+ $wearout = $attr->{raw};
+ }
+ if (defined($wearout)) {
+ if ($flags->{"TYPE"} eq "Lifetime_Remaining") {
+ # it is assumed that "remaining life" will never get nagative value
+ # so, it is converted to wearout ("used")
+ $wearout = 100 - $wearout;
+ }
+ }
last;
}
}
--
2.43.0.windows.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-09 10:56 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 10:56 [PATCH] fix #7551: storage: normalize wearout detection using smartctl fields and types piknew
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox