From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 7142775320 for ; Fri, 4 Jun 2021 15:59:51 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 669121EADA for ; Fri, 4 Jun 2021 15:59:51 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 6E6E21EAD1 for ; Fri, 4 Jun 2021 15:59:47 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 3E00846722 for ; Fri, 4 Jun 2021 15:59:47 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Fri, 4 Jun 2021 15:59:46 +0200 Message-Id: <20210604135946.23293-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.047 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [smart.rs] Subject: [pbs-devel] [PATCH proxmox-backup] fix #3433: use PVE's wearout logic in PBS X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Jun 2021 13:59:51 -0000 in PVE, the logic how wearout gets read from the smartctl output was changed from a vendor -> id map to a sorted list of specific attribute field names. copy that list to pbs (in the same order), and use that to get the wearout in the future we might want to split the disk logic into its own crate and reuse it in pve Signed-off-by: Dominik Csapak --- though we do not have any regression tests here, on my machine it results in identical wearout values (crucial, samsung, intel) please holler if i should implement some smart regression tests here, then i'll try to copy them from pve-storage, so that we can have the same tests for both src/tools/disks/smart.rs | 59 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/tools/disks/smart.rs b/src/tools/disks/smart.rs index d7f05226..b615603e 100644 --- a/src/tools/disks/smart.rs +++ b/src/tools/disks/smart.rs @@ -1,3 +1,6 @@ +use std::collections::{HashMap, HashSet}; + +use lazy_static::lazy_static; use anyhow::{bail, Error}; use ::serde::{Deserialize, Serialize}; @@ -95,10 +98,10 @@ pub fn get_smart_data( let mut wearout = None; let mut attributes = Vec::new(); + let mut wearout_candidates = HashMap::new(); // ATA devices if let Some(list) = output["ata_smart_attributes"]["table"].as_array() { - let wearout_id = lookup_vendor_wearout_id(disk); for item in list { let id = match item["id"].as_u64() { Some(id) => id, @@ -135,8 +138,8 @@ pub fn get_smart_data( None => continue, // skip attributes without threshold entry }; - if id == wearout_id { - wearout = Some(normalized); + if WEAROUT_FIELD_NAMES.contains(&name as &str) { + wearout_candidates.insert(name.clone(), normalized); } attributes.push(SmartAttribute { @@ -151,6 +154,15 @@ pub fn get_smart_data( } } + if !wearout_candidates.is_empty() { + for field in WEAROUT_FIELD_ORDER { + if let Some(value) = wearout_candidates.get(field as &str) { + wearout = Some(*value); + break; + } + } + } + // NVME devices if let Some(list) = output["nvme_smart_health_information_log"].as_object() { for (name, value) in list { @@ -186,27 +198,24 @@ pub fn get_smart_data( Ok(SmartData { status, wearout, attributes }) } -fn lookup_vendor_wearout_id(disk: &super::Disk) -> u64 { - - static VENDOR_MAP: &[(&str, u64)] = &[ - ("kingston", 231), - ("samsung", 177), - ("intel", 233), - ("sandisk", 233), - ("crucial", 202), - ]; - - let result = 233; // default - let model = match disk.model() { - Some(model) => model.to_string_lossy().to_lowercase(), - None => return result, +static WEAROUT_FIELD_ORDER: &[&'static str] = &[ + "Media_Wearout_Indicator", + "SSD_Life_Left", + "Wear_Leveling_Count", + "Perc_Write/Erase_Ct_BC", + "Perc_Rated_Life_Remain", + "Remaining_Lifetime_Perc", + "Percent_Lifetime_Remain", + "Lifetime_Left", + "PCT_Life_Remaining", + "Lifetime_Remaining", + "Percent_Life_Remaining", + "Percent_Lifetime_Used", + "Perc_Rated_Life_Used" +]; + +lazy_static! { + static ref WEAROUT_FIELD_NAMES: HashSet<&'static str> = { + WEAROUT_FIELD_ORDER.iter().cloned().collect() }; - - for (vendor, attr_id) in VENDOR_MAP { - if model.contains(vendor) { - return *attr_id; - } - } - - result } -- 2.20.1