Salta al contenuto principale

hdparm: vedere e regolare i parametri dei dischi

Inviato da tuxsa il

Il disco rotante si ferma e riparte di continuo e il server perde reattività. Un disco nuovo sembra più lento del vecchio. Si vuole sapere se il disco sta davvero collegato alla velocità giusta, o far spegnere i dischi che non si usano per risparmiare corrente e usura. Sono lavori da hdparm: uno strumento per interrogare e regolare i dischi ATA/SATA, e per misurarne in modo rapido la velocità di lettura.

Cos'è

hdparm (hard disk parameters) è un programma di Mark Lord, nato per i dischi IDE e rimasto in uso per quelli SATA (su Debian e Ubuntu: sudo apt install hdparm, vedi l'articolo su apt). Dialoga con il disco attraverso comandi ATA e con il sistema attraverso il kernel (vedi uname). Per i dischi NVMe non serve: hanno i loro strumenti (smartctl, visto nell'articolo precedente, e nvme-cli).

Cosa fa

Mostra l'identità e le funzioni del disco, misura la velocità di lettura, controlla se è acceso o in riposo, e permette di cambiare alcune impostazioni: lo spegnimento automatico dopo un periodo di inattività, la gestione del consumo, la cache di scrittura, la lettura anticipata. Offre anche comandi più delicati: la cancellazione sicura, le funzioni di sicurezza ATA, l'aggiornamento del firmware, che vanno trattati con molta cautela.

Come si usa

$ sudo hdparm [opzioni] dispositivo

Una precisazione importante sulle prove. Nella macchina virtuale che uso per verificare i comandi, hdparm non può nemmeno aprire i dischi: risponde Operation not permitted anche come amministratore, e comunque sono dischi virtuali, senza i comandi ATA. Quindi gli output di hdparm su un disco vero sono illustrativi (valori inventati, formato tratto dal programma v9.65). Fanno eccezione la decodifica dell'identificazione del disco, che ho potuto far eseguire al vero hdparm dandogli in ingresso dei dati inventati (--Istdin, esempio 3), la creazione di file, l'elenco delle opzioni, i messaggi d'errore e la lettura della configurazione. Gli esempi usano web01, il server degli articoli precedenti, con un disco immaginario /dev/sda.

Esempio 1: misurare la velocità di lettura

$ sudo hdparm -T /dev/sda
/dev/sda:
 Timing cached reads:   26816 MB in  2.00 seconds = 13427.74 MB/sec
$ sudo hdparm -t /dev/sda
/dev/sda:
 Timing buffered disk reads: 524 MB in  3.01 seconds = 174.07 MB/sec
$ sudo hdparm -t --direct /dev/sda
$ sudo hdparm -t --offset 1000 /dev/sda
$ sudo hdparm -tT /dev/sda /dev/sdb

Sono i due test più usati. -T (cache) misura la velocità del sistema nel leggere dalla memoria e non dal disco: serve a confrontare processore e memoria, non il disco. -t (timings) misura la lettura vera dal disco, per qualche secondo: 174 MB/s è un valore tipico per un disco rotante di oggi (un SSD SATA ne dà intorno a 500). Con --direct si aggira la cache del sistema, e con --offset N si parte da N GiB dall'inizio del disco: un disco rotante è più veloce all'inizio e più lento alla fine, perciò due misure a offset diversi danno risultati diversi. I test leggono soltanto, e non modificano i dati; i numeri dell'esempio sono illustrativi. Per risultati confrontabili ripeti la misura due o tre volte, a disco inattivo (guarda con top e lsof che nessun programma lo stia usando).

Esempio 2: le impostazioni correnti

$ sudo hdparm /dev/sda
/dev/sda:
 multcount     = 16 (on)
 IO_support    =  1 (32-bit)
 readonly      =  0 (off)
 readahead     = 256 (on)
 geometry      = 486401/255/63, sectors = 7814037168, start = 0
$ sudo hdparm -a /dev/sda
$ sudo hdparm -a 1024 /dev/sda
$ sudo hdparm -r /dev/sda
$ sudo hdparm -g /dev/sda

Senza opzioni, hdparm mostra le impostazioni principali del disco. readahead (-a) è la lettura anticipata: quanti settori da 512 byte il sistema legge in più, "sperando" che servano subito dopo. Alzarla (come nel secondo comando, 1024 settori = 512 KiB) può aiutare con letture sequenziali di file grandi (video, backup), ma non cambia i dischi usati soprattutto a scritture casuali. readonly (-r) dice se il disco è in sola lettura per il sistema: l'impostazione si legge con -r e si cambia con -r1, ma è marcata "pericolosa" nell'aiuto del programma, e di solito si evita. -g mostra la geometria (cilindri, testine, settori: un residuo storico, il numero che conta è sectors). Il valore readahead è per il dispositivo a blocchi: lo mostra anche blockdev --getra /dev/sda.

Esempio 3: identificare il disco

$ sudo hdparm -I /dev/sda
/dev/sda:

ATA device, with non-removable media
    Model Number:       Example DX4000
    Serial Number:      EXD1234567
    Firmware Revision:  DX01
...
Standards:
    Supported: 9 8 7 6 5
    Likely used: 9
Configuration:
    Logical     max current
    cylinders   16383   16383
    heads       16      16
    sectors/track   63  63
    --
    LBA    user addressable sectors:   268435455
    LBA48  user addressable sectors:  7814037168
    Logical  Sector size:                   512 bytes
    Physical Sector size:                  4096 bytes
    device size with M = 1000*1000:     4000787 MBytes (4000 GB)
    Nominal Media Rotation Rate: 7200
Capabilities:
    LBA, IORDY(can be disabled)
    Queue depth: 32
    R/W multiple sector transfer: Max = 16  Current = 16
    DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 udma5 *udma6
$ sudo hdparm -I /dev/sda | grep -E 'Model|Serial|Rotation|Sector size|TRIM'
$ sudo hdparm --Istdout /dev/sda > id-sda.hex
$ hdparm --Istdin < id-sda.hex | tail -n 1
Checksum: correct

Con -I (identify) si leggono i dati direttamente dal disco; -i (minuscola) mostra invece quelli che il sistema aveva raccolto all'avvio, meno aggiornati. Il blocco qui è la decodifica reale, fatta dal vero hdparm, di una scheda di identificazione inventata (ho omesso alcune righe, come Transport molto lunga, e l'elenco completo delle funzioni nella parte Commands/features). Le informazioni da leggere per prime: Model Number e Serial Number (per riconoscere il disco), Physical Sector size (4096 byte: un disco "Advanced Format", e per questo le partizioni vanno allineate a 4 KiB), Nominal Media Rotation Rate (i giri al minuto: per un SSD compare Solid State Device), Queue depth (le richieste che il disco accetta insieme) e la velocità di collegamento. Nella parte Commands/features, dell'elenco completo, le righe con un asterisco sono le funzioni attive: Write cache, Look-ahead, SMART feature set, Native Command Queueing (NCQ); in fondo ci sono il blocco Security (se il disco è bloccato con una password) e Checksum. Gli ultimi due comandi mostrano che i dati si possono salvare (--Istdout) e poi rileggere su un'altra macchina (--Istdin), come ho fatto io per questo articolo; il secondo l'ho eseguito davvero, sui dati inventati.

Esempio 4: spegnere il disco quando non serve

$ sudo hdparm -C /dev/sda
/dev/sda:
 drive state is:  active/idle
$ sudo hdparm -S 240 /dev/sda
/dev/sda:
 setting standby to 240 (20 minutes)
$ sudo hdparm -y /dev/sda
$ sudo hdparm -C /dev/sda
/dev/sda:
 drive state is:  standby
$ sudo hdparm -S 0 /dev/sda

-C (check) mostra lo stato di alimentazione: active/idle (acceso), standby (i dischi rotanti sono fermi) o sleeping. Con -S (standby) si imposta il tempo di inattività dopo il quale il disco si ferma da solo: il valore è un codice, non i minuti. Da 1 a 240 sono multipli di 5 secondi (quindi -S 240 = 1200 secondi = 20 minuti, e -S 120 = 10 minuti); da 241 a 251 sono multipli di 30 minuti (-S 241 = 30 minuti, -S 242 = 1 ora); -S 0 disattiva lo spegnimento automatico. Con -y si manda il disco in standby subito; -Y lo mette in "sleep", uno stato più profondo da cui di solito serve un ripristino: meglio evitarlo. La gestione del consumo, -B (APM), prende un valore da 1 a 255: i valori bassi risparmiano energia (e possono rallentare), 255 la disattiva. Gli output dell'esempio sono illustrativi; il messaggio setting standby to 240 (20 minutes) è quello che stampa il programma.

Esempio 5: la cache di scrittura

$ sudo hdparm -W /dev/sda
/dev/sda:
 write-caching =  1 (on)
$ sudo hdparm -W 0 /dev/sda
$ sudo hdparm -F /dev/sda

Quasi tutti i dischi hanno una piccola memoria in cui accumulano le scritture prima di scriverle sul supporto: la cache di scrittura. Aumenta la velocità, ma se manca la corrente le scritture ancora in memoria vanno perse, e il file system può risultare danneggiato. -W senza valore la mostra; -W 0 la disattiva (più sicuro, ma più lento), -W 1 la riattiva. -F forza lo svuotamento della cache sul supporto. Il sistema (con sync e i journal dei file system) di norma gestisce da sé lo svuotamento nei momenti giusti, quindi la scelta riguarda i casi in cui l'alimentazione non è protetta (senza gruppo di continuità) e i dati sono molto importanti. Una impostazione cambiata così non è permanente: al riavvio, o allo spegnimento del disco, torna al valore di fabbrica (esempio 6).

Esempio 6: rendere le impostazioni permanenti

$ grep -v '^#' /etc/hdparm.conf | grep -v '^$'
quiet
$ sudo nano /etc/hdparm.conf
/dev/disk/by-id/ata-EXAMPLE_DX4000_EXD1234567 {
    spindown_time = 240
    write_cache = on
}
$ cat /lib/udev/rules.d/85-hdparm.rules
ACTION=="add", SUBSYSTEM=="block", KERNEL=="[sh]d[a-z]", RUN+="/lib/udev/hdparm"

Le impostazioni cambiate con hdparm si perdono allo spegnimento. Per applicarle a ogni avvio, su Debian e Ubuntu si usa il file /etc/hdparm.conf (si modifica con nano: vedi l'articolo relativo). Nel pacchetto è quasi tutto commentato: l'unica riga attiva è quiet (vera: l'ho letta). La sintassi è un blocco per disco, DISCO { opzione = valore }, dove ogni opzione ha un nome che corrisponde a una lettera di hdparm (spindown_time è -S, write_cache è -W, apm è -B, read_ahead_sect è -a: l'elenco è nei commenti del file, che ho letto). Si indica il disco con il percorso stabile /dev/disk/by-id/... invece di /dev/sda, perché il nome sda può cambiare da un avvio all'altro (vedi lsblk); il nome del disco dell'esempio è inventato. Il file ha una regola per udev (anche questa letta e riportata sopra) che esegue lo script del pacchetto quando compare un disco sd o hd: è lui che applica il contenuto di hdparm.conf. Attenzione alla sintassi: il file avverte che ogni riga non commentata viene interpretata dagli script, e che un errore può dare effetti inattesi sul disco.

Esempio 7: file e frammentazione, e cancellazione sicura

$ sudo hdparm --fallocate 1024 prova.bin
$ ls -l prova.bin
-rw------- 1 root root 1048576 Nov  9 06:44 prova.bin
$ sudo hdparm --fibmap /var/lib/mysql/ibdata1
$ sudo hdparm --security-help | head -n 8

ATA Security Commands:
 Most of these are VERY DANGEROUS and can destroy all of your data!
 Due to bugs in older Linux kernels, use of these commands may even
 trigger kernel segfaults or worse.  EXPERIMENT AT YOUR OWN RISK!

 --security-freeze           Freeze security settings until reset.

Qualche funzione meno nota. --fallocate N crea subito un file di N KiB senza scrivere i dati (provato nel sandbox: con 1024 ha creato un file da 1 MiB). --fibmap mostra dove si trovano sul disco i blocchi di un file, e quindi quanto è frammentato: non ho potuto provarlo nel sandbox (richiede l'accesso al dispositivo). Infine il gruppo di opzioni --security-* gestisce le funzioni di sicurezza ATA: password sul disco, cancellazione sicura con --security-erase (che azzera il disco in modo irreversibile, con tempi che dipendono dal modello e si leggono in -I). --security-help le descrive; l'avviso in testa (vero, riportato qui) è chiaro: queste operazioni possono distruggere tutti i dati. Non le descrivo per esteso, perché un errore (disco sbagliato, password persa) non si può rimediare: se ti servono, leggi il manuale e prova prima su un disco senza dati.

Esempio 8: uso negli script

#!/bin/bash
# Imposta lo spegnimento dopo 20 minuti di inattività sui dischi rotanti
DISCHI=$(lsblk -d -n -o NAME,TYPE,ROTA |
         awk '$2 == "disk" && $3 == 1 {print "/dev/" $1}')
for DISCO in $DISCHI; do
    if hdparm -q -S 240 "$DISCO" 2>/dev/null; then
        echo "$DISCO: spegnimento dopo 20 minuti impostato"
    else
        echo "$DISCO: impostazione non riuscita" >&2
    fi
done

Lo script cerca con lsblk i dischi rotanti (ROTA uguale a 1: gli SSD hanno 0 e si lasciano stare) e imposta lo spegnimento automatico; per ognuno stampa l'esito, in base al codice di uscita di hdparm (vedi gli articoli su lsblk e awk). Va lanciato come amministratore. L'ho provato così: con il vero hdparm nel sandbox, che non può aprire i dischi, risponde "impostazione non riuscita" per ognuno; con un finto hdparm che riesce solo su due dischi, stampa l'esito giusto per ciascuno. Nel sandbox ROTA vale 1 anche per i dischi virtuali, quindi sono tutti selezionati. Su un server vero è uno strumento da usare con attenzione: lo spegnimento ripetuto di un disco rotante ne accorcia la vita, e non si usa in un RAID o in un volume ZFS senza averne valutato gli effetti.

Opzioni utili

  • -T: velocità della cache; -t: velocità di lettura dal disco; --direct, --offset N: con -t.
  • -i, -I: identificazione del disco (-I è diretta e più completa); --Istdout, --Istdin: salva e rileggi i dati di identificazione.
  • -C: stato di alimentazione; -S valore: spegnimento dopo l'inattività; -y: standby subito; -B valore: gestione del consumo; -M valore: rumorosità.
  • -W 0|1: cache di scrittura; -F: svuota la cache del disco; -A 0|1: lettura anticipata nel disco; -a N: lettura anticipata nel sistema.
  • -r, -g, -z: sola lettura, geometria, rilettura della tabella delle partizioni.
  • --fallocate, --fibmap, --read-sector: crea un file, mostra i blocchi di un file, legge un settore.
  • -q: silenzioso; -v: opzioni predefinite; -V: versione; -h: aiuto.
  • /etc/hdparm.conf: la configurazione permanente; smartctl, lsblk, fstrim: salute del disco, dispositivi, rilascio dei blocchi inutilizzati di un SSD.

Attenzione a

  • Alcune opzioni possono distruggere i dati o il disco: l'aiuto del programma stesso le marca DANGEROUS o VERY DANGEROUS (-N, -J, -w, -X, --make-bad-sector, --write-sector, --repair-sector) o EXTREMELY DANGEROUS (--fwdownload, l'aggiornamento del firmware). Non provarle su un disco con dati che ti servono, e prima di usarle leggi il manuale (man hdparm).
  • Sono dischi ATA/SATA: per i dischi NVMe non funziona (usa smartctl e nvme-cli), e per i dischi dietro un controller RAID o un adattatore USB il risultato può essere vuoto o incompleto: i comandi ATA non sempre passano.
  • Serve sudo, e nelle macchine virtuali e nei container i dischi sono virtuali: nel sandbox non riesce nemmeno ad aprirli (Operation not permitted, verificato).
  • -t è un'indicazione, non un benchmark: misura solo la lettura sequenziale, e dipende da cosa sta facendo il disco in quel momento, dalla porta e dal cavo, e dalla posizione sul disco. Per misurare scritture, letture casuali e carichi veri servono strumenti come fio o dd.
  • Lo spegnimento frequente consuma i dischi rotanti: ogni arresto e riavvio è uno sforzo meccanico. Un -S troppo corto su un server con accessi frequenti fa ripartire il disco di continuo (si vede dal contatore Load_Cycle_Count di smartctl -A). Su un server sempre in uso, meglio non impostarlo.
  • Le impostazioni non sono permanenti: si perdono al riavvio, e alcuni dischi le perdono anche dopo uno standby profondo. Usa /etc/hdparm.conf, e verifica dopo un riavvio con hdparm senza opzioni.
  • Disattivare la cache di scrittura rallenta molto: attivare -W 0 solo se serve davvero (alimentazione non protetta e dati critici); con un file system con journal e un gruppo di continuità, di solito non serve.
  • Gli SSD vanno trattati in modo diverso: per loro lo spegnimento (-S) non ha senso, e la cancellazione sicura di un SSD con --security-erase o con l'azzeramento non dà le garanzie di un disco rotante, perché il controller sposta i dati. Per liberare i blocchi inutilizzati si usa fstrim.

Riepilogo

ComandoCosa fa
sudo hdparm -t /dev/sdaMisura la velocità di lettura del disco
sudo hdparm -T /dev/sdaMisura la velocità della cache (memoria)
sudo hdparm /dev/sdaMostra le impostazioni principali
sudo hdparm -I /dev/sdaIdentificazione completa, direttamente dal disco
sudo hdparm -C /dev/sdaStato di alimentazione (active, standby)
sudo hdparm -S 240 /dev/sdaSpegne il disco dopo 20 minuti di inattività
sudo hdparm -y /dev/sdaManda il disco in standby subito
sudo hdparm -W /dev/sdaMostra la cache di scrittura (-W 0 la disattiva)
sudo hdparm -a 1024 /dev/sdaCambia la lettura anticipata
sudo hdparm --fallocate 1024 fileCrea un file da 1 MiB senza scrivere i dati
/etc/hdparm.confImpostazioni permanenti (Debian e Ubuntu)