Linux : Corriger des secteurs défecteux sur un disque

Ces derniers temps, j'ai eu plusieurs fois un comportement curieux de l'O.S. et des disques : une ou plusieurs partitions se trouvaient tout à coup en lecture seule, alors qu'elles étaient montées en read/write au boot.

En lançant dmesg, on se retrouve également avec des erreurs :

ata1.00: irq_stat 0x40000008
[ 2639.557921] ata1.00: failed command: READ FPDMA QUEUED
[ 2639.557928] ata1.00: cmd 60/00:08:e8:d7:6a/01:00:03:00:00/40 tag 1 ncq 131072 in
[ 2639.557928]          res 41/40:00:0a:d8:6a/00:00:03:00:00/40 Emask 0x409 (media error) 
[ 2639.557932] ata1.00: status: { DRDY ERR }
[ 2639.557934] ata1.00: error: { UNC }
[ 2639.563242] ata1.00: configured for UDMA/133
[ 2639.563280] sd 0:0:0:0: [sda] Unhandled sense code

Bref, des soucis potentiels sur le disque, qui n'était pourtant pas bien vieux.

Heureusement, tout ceci peut se résoudre, avec un peu d'huile de coude et de ligne de commande.

L'outil à tout faire : smartctl

smartctl est un utilitaire qui permet d'avoir un contrôle intelligent (smart control) sur le disque.
Il s'installe (sous debian & Co) via la commande :

apt-get install smartmontools

Vérification

On peut lancer un test court avec l'utilitaire :

# smartctl -t short /dev/sda
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-3.5.0-23-generic] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Short self-test routine immediately in off-line mode".
Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 2 minutes for test to complete.
Test will complete after Sun Jan 27 22:00:30 2013

Comme le dit le retour, le script prend moins de 2 minutes. On peut alors visualiser le résultat via la commande :

# smartctl -l selftest /dev/sda
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Short offline       Completed: read failure       90%      1662         54678673

On peut détecter le problème avec la commande :

# smartctl -a /dev/sda 
SMART Attributes Data Structure revision number: 16 Vendor Specific 
SMART Attributes with Thresholds: 
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 
.../... 
5 Reallocated_Sector_Ct 0x0033 200 200 140 Pre-fail Always - 0 
196 Reallocated_Event_Count 0x0032 200 200 000 Old_age Always - 0 
197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 9 
198 Offline_Uncorrectable 0x0030 100 253 000 Old_age Offline - 0 

On voit ici qu'il existe 9 secteurs en attente de réallocation... Un peu de travail manuel en perspective !

Deuxième étape : détermination de la partition incriminée

Il faut déterminer dans quelle partition se trouve le bloc fautif.

# fdisk -l

Disk /dev/sda: 320.1 GB, 320072933376 bytes
255 têtes, 63 secteurs/piste, 38913 cylindres, total 625142448 secteurs
Unités = secteurs de 1 * 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Identifiant de disque : 0x0005486a

Périphérique Amorce  Début        Fin      Blocs     Id  Système
/dev/sda1   *        2048    39063551    19530752   83  Linux
/dev/sda2        39065598   625141759   293038081    5  Étendue
/dev/sda5        39065600    48828415     4881408   82  partition d'échange Linux / Solaris
/dev/sda6        48830464   205078527    78124032   83  Linux
/dev/sda7       205080576   625141759   210030592   83  Linux

On constate que notre numéro de bloc 54678673 est compris entre le début et la fin de la partition /dev/sda6.
Il faut ensuite déterminer la taille d'un bloc :

# tune2fs -l /dev/sda6 | grep Block
Block count:              19531008
Block size:               4096
Blocks per group:         32768

La taille du bloc est de 4096, ce qui est généalement le cas.

Troisième étape : déterminer dans quel bloc se trouve le secteur fautif

La formule est : b = (int)((L-S)*512/B), avec:

  • b = Bloc du File System
  • B = Taille du bloc en octets (4096)
  • L = LBA du mauvais secteur
  • S = Secteur de début de la partition, tel que le donne la commande fdisk -l
  • (int) pour prendre la partie entière

Dans notre exemple, L=54678673, S=48830464, et B=4096.
Ainsi le bloc à problème est :

b = (int)(54678673 - 48830464)*512/4096 = (int)5848209*512/4096 = (int)731026,125
donc b=731026.

Quatrième étape : déterminer le fichier incriminé

On utilise pour cela la commande debugfs :

# debugfs
debugfs 1.42.5 (29-Jul-2012)
debugfs:  open /dev/sda6
debugfs:  testb 731026
Block 731026 marked in use
debugfs:  icheck 731026
Block	Inode number
731026	4327016
debugfs:  ncheck 4327016
Inode	Pathname
4327016	/lucie/.local/share/zeitgeist/activity.sqlite-wal
debugfs:  quit

Le détail des commandes :

  • open /dev/sda6 : on utilise cette partition
  • testb 731026 : vérification si le bloc est utilisé. Le bloc est marqué comme in use/li>
  • icheck 731026 : identification de l'inode contenu dans le bloc
  • ncheck 4327016 : identification du fichier correspondant à l'inode

Dans notre cas, c'est un fichier de zeitgeist qui est fautif ; il pourra être écrasé sans trop de soucis.

Cinquième étape : réallocation du bloc

Attention ! La commande suivante permet de remplir le bloc avec des 0, et de réallouer l'espace disque. C'est dans ce cas là qu'on est content de ne pas avoir oublié ses sauvegardes. Commande à manier avec précaution donc :

# dd if=/dev/zero of=/dev/sda6 bs=4096 count=1 seek=731026
# sync

On peut alors vérifier avec la commande smartctl -a /dev/sda pour vérifier s'il reste des blocs en Pending. On peut aussi relancer un test, et vérifier que celui-ci s'est terminé sans erreur :

# smartctl -l selftest /dev/sda
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-3.5.0-23-generic] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Short offline       Completed without error       00%      1667         -
# 2  Short offline       Completed: read failure       90%      1666         367177080

A ce niveau, on peut éventuellement ressortir les sauvegardes pour restaurer les fichiers touchés par la manipulation... et en profiter pour refaire une sauvegarde complète du système.

Références

Quelques pages qui m'ont bien aidées :

 

 

 

 

Catégorie