Ręczne realokowanie sektorów na dysku
Kategoria: Artykuły, etykiety: smartmontools, smartctl, smart, hdd, dysk, bad sector, bad block
Dodany: 2013-11-22 05:34
(zmodyfikowany: 2013-12-09 19:21)
Przez: morfik
Wyświetleń: 8290
Po 18.798 godzinach pracy, mój główny dysk złapał prawdopodobnie bad sektora. W logu smart można przeczytać info o takim błędzie:
Error 25 occurred at disk power-on lifetime: 18798 hours (783 days + 6 hours)
When the command that caused the error occurred, the device was active or idle.
After command completion occurred, registers were:
ER ST SC SN CL CH DH
-- -- -- -- -- -- --
40 51 08 00 40 37 e6 Error: UNC 8 sectors at LBA = 0x06374000 = 104284160
Commands leading to the command that caused the error were:
CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name
-- -- -- -- -- -- -- -- ---------------- --------------------
c8 00 08 00 40 37 e6 08 08:54:35.771 READ DMA
ec 00 00 00 00 00 a0 08 08:54:35.763 IDENTIFY DEVICE
ef 03 46 00 00 00 a0 08 08:54:35.763 SET FEATURES [Set transfer mode]
Problemy z sektorami można zauważyć również w /var/log/messages . Poniżej linijka, która pokaże, czy są jakieś wzmianki o nich:
# grep LBA /var/log/messages* | awk '{print $9}' | sort | uniq
156299375
2930275055
976817134
No tak 3 kolejne i żaden z nich nie odpowiada temu, co siedzi w raporcie smart. To niekoniecznie muszą być bad sektory ale każdy wymieniony sektor trzeba sprawdzić pod kątem odczytu, być może były tam jakieś problemy wcześniej i temu system to zanotował ale niekoniecznie oznacza, że problemy występują dalej. Najlepiej po prostu odpytać te sektory i jeśli dadzą się czytać, wszystko jest ok i można o nich zapomnieć. No to do dzieła:
# hdparm --read-sector 156299375 /dev/sda
/dev/sda:
reading sector 156299375: succeeded
# hdparm --read-sector 2930275055 /dev/sda
/dev/sda:
reading sector 2930275055: succeeded
# hdparm --read-sector 976817134 /dev/sda
/dev/sda:
reading sector 976817134: succeeded
Oczywiście, tych sektorów w logu może być więcej, ja mam w miarę świeży system i logów jako takich za dużo w nim jeszcze się nie zdążyło nazbierać.
Przy czym taka uwaga. Jeśli pojawiają się błędy w liczbie sektorów 8 (tak jak w tym przypadku), oznacza to prawdopodobnie, że dysk używa advanced format, czyli ma sektory nie 512 bajtów, a 8*512=4096 bajtów. Ja o tym nie wiedziałem na początku, bo mój dysk wyraźnie zwracał wartość 512 w każdym możliwym miejscu i dalej zwraca pomimo faktu, że ma sektory 4096.
Przy próbie odczytu bad sektora, w syslogu można zobaczyć taki komunikat:
Nov 21 12:57:29 morfikownia kernel: [ 5503.342060] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
Nov 21 12:57:29 morfikownia kernel: [ 5503.342069] ata1.01: failed command: READ SECTOR(S)
Nov 21 12:57:29 morfikownia kernel: [ 5503.342077] ata1.01: cmd 20/00:01:00:40:37/00:00:00:00:00/f6 tag 0 pio 512 in
Nov 21 12:57:29 morfikownia kernel: [ 5503.342077] res 51/40:01:00:40:37/40:00:06:00:00/f6 Emask 0x9 (media error)
Nov 21 12:57:29 morfikownia kernel: [ 5503.342082] ata1.01: status: { DRDY ERR }
Nov 21 12:57:29 morfikownia kernel: [ 5503.342085] ata1.01: error: { UNC }
Nov 21 12:57:29 morfikownia kernel: [ 5503.379301] ata1.01: configured for UDMA/133
Nov 21 12:57:29 morfikownia kernel: [ 5503.379331] ata1: EH complete
Mi on nic nie mówi, no może poza tym, że jest błąd odczytu sektora. Co ciekawe dysk sam nie realokował go. W tabelce smart widnieje ciągle:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x002f 200 200 051 Pre-fail Always - 1
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 - 1
198 Offline_Uncorrectable 0x0030 200 200 000 Old_age Offline - 2
Czemu sektor nie jest remapowany automatycznie? Dzieje się tak dlatego, że w tym sektorze rezyduje jakiś plik, lub część jakiegoś pliku. Sektor może być realokowany tylko przy zapisie danych na dysk, a nie przy ich odczycie. Przy odczycie dostaje się tylko błęda. W tym wypadku zapis wadliwego sektora nie może się odbyć, bo miejsce jest zajęte przez plik, dlatego też raport smart pokazuje błąd odczytu bez remapowania sektora, co wskazuje na uszkodzony plik, który trzeba zlokalizować. Ok, może nie trzeba, wystarczy pewnie nadpisać ponownie ten sektor siłowo i ma się spokój, przynajmniej do czasu gdy zajdzie potrzeba skorzystania z tego pliku. xD Ja postaram się doszukać nieco więcej informacji na temat tego zdarzenia. Tylko jak ustalić jaki to plik i gdzie te sektory dokładnie się znajdują i co oznacza LBA = 104284160 w raporcie smart?
Zgodnie z tym co piszą na wiki: LBA (ang. Logical Block Addressing) - metoda obsługi dysku twardego przez system operacyjny. I aby go wyliczyć, trzeba skorzystać z poniższego wzoru:
LBA = ( numer_cylindra * liczba_glowic_na_cylinder + numer_glowicy ) * liczba_sektorow_na_sciezke + numer_sektora -1
Hmmm, taa, a nie da się jakoś po ludzku? Da się. Przede wszystkim musimy ustalić, na której partycji występuje bad sektor. To jest akurat stosunkowo proste. Można skorzystać z fdiska i popatrzyć po początkach i końcach partycji i jeśli bad sektor się zawiera w którymś z przedziałów, oznacza to, że partycja zawierająca bad sektor została zlokalizowana. Tak wygląda struktura mojego dysku:
root:~# fdisk -lu /dev/sda
Disk /dev/sda: 1500.3 GB, 1500301910016 bytes
255 heads, 63 sectors/track, 182401 cylinders, total 2930277168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000a8aae
Device Boot Start End Blocks Id System
/dev/sda1 * 2048 1953791 975872 83 Linux
/dev/sda2 1953792 99610623 48828416 83 Linux
/dev/sda3 99610624 1466798079 683593728 83 Linux
/dev/sda4 1466800126 2930276351 731738113 5 Extended
/dev/sda5 1857425408 2482423807 312499200 83 Linux
/dev/sda6 2482425856 2930276351 223925248 83 Linux
/dev/sda7 1466802176 1646376959 89787392 83 Linux
/dev/sda8 1646379008 1857423359 105522176 83 Linux
Partition table entries are not in disk order
Liczba 104284160 (ta z błędu smart) zawiera się w przedziale 99610624-1466798079 , także bad sektor znajduje się na 3 partycji. W przypadku posiadania kilku bad sektorów, poniższe kroki trzeba zastosować do każdego z nich. W każdym razie, mając już trefną partycję, nasuwa się pytanie o dokładne miejsce gdzie sektorowi się padło. To można z kolei wyliczyć (choć nie wiem po co) ze wzoru:
104284160 - 99610624 = 4673536
Czyli od lokalizacji bad sektora odjąć trzeba początek partycji, na której ten sektor się pojawił. W każdym razie nas bardziej interesuje start partycji i lokalizacja sektora. Są to dwie zmienne, które będą nam potrzebne do późniejszego równania, oznaczmy je sobie L oraz S -- L=104284160 , S=99610624 . Musimy pozyskać jeszcze jedną zmienną -- rozmiar bloku, a ten z kolei możemy wyciągnąć przez:
# tune2fs -l /dev/mapper/crypt_filmy | grep Block
Block count: 170897920
Block size: 4096
Blocks per group: 32768
Oczywiście ja używam zaszyfrowanych partycji temu odwołuję się do urządzeń w /dev/mapper/ . Standardowo jednak są to partycje typu /dev/sda2 , etc. Czyli rozmiar bloku systemu plików to 4096. Jest to nasza zmienna B. Teraz podstawiamy to wszystko do wzoru:
b = (int)((L-S)*512/B)
b = (int)((104284160-99610624)*512/4096
b=584192
(int) bierze z wyniku liczbę całkowitą. W ten sposób uzyskaliśmy numer wadliwego bloku widzianego przez system plików na danej partycji. Musimy zbadać ten blok przy pomocy debugfs:
# debugfs
debugfs 1.42.8 (20-Jun-2013)
debugfs: open /dev/mapper/crypt_filmy
debugfs: testb 584192
Block 584192 marked in use
debugfs: icheck 584192
Block Inode number
584192 37486656
debugfs: ncheck 37486656
Inode Pathname
37486656 /gry/World of Warcraft 3.3.5a (no install)/Data/patch.MPQ
Polecenie open przechodzi do analizy systemu plików na wskazanej partycji. Następnie przy pomocy testb sprawdzamy czy dany blok jest w użyciu czy też nie. Jeśli jest, znaczy, że znajduje się tam plik. Sprawdzamy zatem przy pomocy icheck, który inode używa tego bloku, a następnie przy pomocy ncheck sprawdzamy jaka ścieżka pliku na dysku jest mu przypisana. Po nitce do kłębka i tak znaleźliśmy plik, którego dane znajdują się na uszkodzonym sektorze. No taa, też nie miało gdzie tego sektora wywalić. xD
Co oznacza, że plik znajduje się w obszarze bad sektora? Najlepiej odpowiedzieć na to pytanie poprzez próbę skopiowania tego pliku:
root:~# ls -al "/media/Filmy/gry/World of Warcraft 3.3.5a (no install)/Data/patch.MPQ"*
-rwxrwx--- 1 morfik morfik 3.8G Jul 8 2012 /media/Filmy/gry/World of Warcraft 3.3.5a (no install)/Data/patch.MPQ*
-rwxrwx--- 1 morfik morfik 1.2G Jul 8 2012 /media/Filmy/gry/World of Warcraft 3.3.5a (no install)/Data/patch.MPQ_back*
Jak widać skopiowało się tylko 1.2GiB danych z faktycznych 3.8GiB . Zaglądając w tym czasie do smart, można odnotować kilka kolejnych błędów. Jeśli tak się stało, znaczy, że znaleźliśmy winowajcę. Oczywiście nie da się już tego pliku skopiować, dysk przywiesza system przy próbie odczytu wadliwego sektora, jedyne co można zrobić to usunąć plik z systemu, a właściwie zwolnić inode oraz ręcznie realokować ten sektor przy pomocy dd lub hdparm.
Nie jestem pewien czy operację realokowania sektorów trzeba przeprowadzać bezpośrednio na urządzeniu /dev/sda (ew. partycjach sda1) czy można to też robić na urządzeniach w /dev/mapper/ . Na logikę, to raczej nie powinno mieć znaczenia. W każdym razie odmontujmy system plików:
# umount /media/Filmy
Teraz można dokonać remapowania zapisując przy pomocy dd dane z /dev/zero do wadliwego sektora partycji /dev/sda3 albo /dev/mapper/crypt_filmy
# dd if=/dev/zero of=/dev/mapper/crypt_filmy bs=4096 count=1 seek=584192
# sync
Teoretycznie w ten sposób wyzerowany (nadpisany) sektor zostanie realokowany i już nigdy więcej dane do wadliwego bloku nie trafią. U mnie to nie zdało rezultatu być może dlatego, że próbowałem przez /dev/mapper/, w każdym razie, próba nadpisania tego sektora wyrzucała błąd zapisu.
Być może trzeba było od razu podać of=/dev/sda3. Przy czym tu istotna sprawa -- przy zapisie danych bezpośrednio na partycję, ogromne znaczenie ma parametr bs, a on z kolei zależy od tego czy dysk ma 512 czy 4096 bajtowe sektory. W przypadku takim jak mój gdzie ciężko było to oszacować, można spróbować techniki na jeża, czyli ustawić bs=512 oraz count=1. Jeśli sektor nie zostanie realokowany, prawdopodobnie mamy do czynienia z sektorami 4096, bo w takim przypadku, by sektor został realokowany potrzeba jest zapisanie pozostałych 7 sektorów by wypełnić 4096 bajtów. Można to albo ustawić przez bs=512 count=8 albo bs=4096 count=1. Należy pamiętać, że w obu przypadkach zostanie nadpisanych 4096 bajtów i jeśli mamy 512 bajtowy sektor, to możemy mieć problemy. Ponadto, parametr seek powinien też być wielokrotnością 8 przy 4096 bajtowych sektorach.
Smart powinien automatycznie zaktualizować odpowiednie atrybuty. Niektóre dyski jednak wymagają by dokonać tego ręcznie przez:
# smartctl -t offline /dev/sda
smartctl 6.2 2013-07-26 r3841 [x86_64-linux-3.12-0.slh.3-aptosid-amd64] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART off-line routine immediately in off-line mode".
Drive command "Execute SMART off-line routine immediately in off-line mode" successful.
Testing has begun.
Please wait 26460 seconds for test to complete.
Test will complete after Thu Nov 21 10:43:09 2013
Use smartctl -X to abort test.
Test będzie trwał ładnych parę godzin, oczywiście można używać pc jak gdyby nigdy nic ale im bardziej będzie dysk obciążony, tym wolniej zostanie przeskanowany.
Ja za bardzo nie wiedziałem w czym tkwi problem z realokowaniem mojego bad bloka, dlatego też posłużyłem się hdparm. Chciałem sprawdzić czy jemu się uda realokować padnięty sektor:
# hdparm --yes-i-know-what-i-am-doing --write-sector 104284160 /dev/sda
/dev/sda:
re-writing sector 104284160: succeeded
W końcu jakiś postęp. Sprawdźmy zatem co smart powie:
# smartctl -A /dev/sda | egrep "Reallocated|Pending|Uncorrectable"
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 - 0
198 Offline_Uncorrectable 0x0030 200 200 000 Old_age Offline - 2
A to dopiero dziwne, wartość atrybutu 197 została wyzerowana, poprzednio była tam wartość 1 ale atrybut 5 tez ma zero. Szukając info na ten temat, okazało się, że nawet takie problemy z sektorem jak ja miałem, nie koniecznie oznaczają, że sektor będzie skazany na zapomnienie i odesłany w nicość. Gdy tego typu sytuacja się przytrafia, oznacza to nic innego jak przywrócenie sektora do życia, czyli udało się go odblokować.
W przypadku gdyby się nie udało, raport smart by wyglądał jak poniżej:
5 Reallocated_Sector_Ct 0x0033 200 200 140 Pre-fail Always - 1
196 Reallocated_Event_Count 0x0032 200 200 000 Old_age Always - 1
197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 0
198 Offline_Uncorrectable 0x0030 200 200 000 Old_age Offline - 2
Zostanie wyzerowany atrybut 197, a do atrybutów 5 i 196 zostanie dopisane +1. Natomiast atrybut 198 nie zostanie zmieniony. Po zakończeniu prac, przeprowadzić musimy jeszcze test skanowania całej powierzchni dysku:
# smartctl -t long /dev/sda
Powinno to wyzerować atrybut 198 -- u mnie, po przejściu go, atrybut 198 nadal ma wartość 2 i nie mam zielonego pojęcia jak się go pozbyć. Przejście testu powinno też zapalić zieloną lampkę i oznaczyć urządzenie jako sprawne.
Poniżej info o testach mojego dysku:
# smartctl -l selftest /dev/sda
smartctl 6.2 2013-07-26 r3841 [x86_64-linux-3.12-0.slh.3-aptosid-amd64] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
=== 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% 18858 -
# 2 Extended offline Completed without error 00% 18858 -
# 3 Conveyance offline Completed without error 00% 18854 -
# 4 Short offline Completed without error 00% 18853 -
# 5 Short offline Completed: read failure 90% 18852 104284160
# 6 Short offline Completed: read failure 90% 18845 104284160
# 7 Short offline Completed: read failure 90% 18839 104284160
# 8 Short offline Completed: read failure 90% 18837 104284160
# 9 Short offline Completed: read failure 90% 18836 104284160
#10 Short offline Completed: read failure 90% 18836 104284160
#11 Short offline Completed: read failure 90% 18836 104284160
#12 Short offline Completed without error 00% 18673 -
#13 Short offline Completed without error 00% 18498 -
#14 Short offline Completed without error 00% 85 -
7 of 7 failed self-tests are outdated by newer successful extended offline self-test # 2
Oraz log chwilę po ukończeniu skanowania:
Nov 22 01:05:51 morfikownia smartd[3463]: Device: /dev/sda [SAT], 2 Offline uncorrectable sectors
Nov 22 01:05:51 morfikownia smartd[3463]: Device: /dev/sda [SAT], previous self-test completed without error
Nov 22 01:05:51 morfikownia smartd[3463]: Device: /dev/sda [SAT], Self-Test Log error count decreased from 7 to 0
Nov 22 01:05:51 morfikownia smartd[3463]: Device: /dev/sda [SAT], Self-Test Log does no longer report errors, warning condition reset after 1 email
Na wzmiankę zasługuje jeszcze jedna kwestią -- co by się stało gdyby wadliwy sektor pojawił się w dzienniku partycji? Z reguły można to poznać po bardzo niskich numerach inode, jak wtedy powstrzymać dysk od sypania błędami? W takiej sytuacji trzeba usunąć niestety cały dziennik:
# tune2fs -O ^has_journal /dev/sda3
Po tym kroku postępujemy dokładnie tak jak w przypadku zwykłego bad sektora. Gdy już realokujemy sektor, trzeba stworzyć dziennik na nowo:
# tune2fs -j /dev/sda3
Co prawda u mnie udało się wyleczyć dysk z bad sektora ale pierwszy padnięty sektor nie oznacza, że trzeba od razu lecieć do sklepu z zamiarem kupna nowego urządzenia. Trzeba tylko monitorować czy aby liczba padniętych sektorów się czasem nie zwiększa. Oczywiście każdy padnięty sektor oznacza utratę danych, w tym przypadku dość kosztowną, bo prawie 4GiB. Choć w sumie jakby to był film, to pewnie dałoby radę wyciąć kawałek od początku filmu do sektora i od sektora do końca filmu, a potem oba kawałki złączyć i może nawet by nie było zauważalnej różnicy. xD
Aktualizacja:
Udało mi się znaleźć trochę info ma temat parametru 198 Offline_Uncorrectable . Wychodzi na to, że część dysków nie resetuje go, nawet po pomyślnym przejściu testu. Za to smartd domyślnie ma ustawione informowanie o niezerowej wartości tego atrybutu. I stąd to ostrzeżenie w syslogu. Czyli chyba nie da się z tym nic zrobić ale można poinstruować smartd by wyrzucał komunikat tylko w przypadku gdy wartość tego atrybutu zostanie zwiększona w stosunku do wartości zapisanej przy poprzednim skanowaniu -- czyli jeśli teraz mam wartość 2, to ostrzeżenie pojawi się gdy będzie tam widniało 3 i więcej.
By zmienić konfigurację smartd, edytujemy plik /etc/smartd.conf . Teraz musimy tam dopisać poniższą linijkę:
/dev/sda -H -l error -l selftest -t -R 1 -R 5 -R 7 -R 10 -R 11 -R 192 -R 196 -R 197 -R 198 -R 199 -R 200 -U 198+
Koniecznie musi ona się pojawić przed wystąpieniem DEVICESCAN, inaczej zostanie zignorowana. W przypadku posiadania większej ilości dysków, po prostu dodajemy kolejną linijkę odpowiednio zmieniając plik urządzenia.
Wyjaśnienie parametrów:
- -H -- monitoruje SMART Health Status i zgłasza jeśli są problemy.
- -l -- Monitoruje logi SMART. Są możliwe do zdefiniowania dwie opcje -- error oraz selftest -- jeśli któryś z nich zgłosi błąd, zostaniemy o tym poinformowani.
- -t -- zgłasza zmiany atrybutów w tabeli SMART. Jeśli nie ma parametru -R, monitorowane są wszystkie.
- -R -- definiuje atrybuty do monitorowania. Np. temperatura, która u mnie ma 28 stopni nie musi być monitorowana, temu nie jest uwzględniony min. atrybut 194. Zawsze to trochę mniej operacji zapisu/odczytu na dysku.
- -U -- domyślnie ta opcja wskazuje na parametr 198 (można wybrać inny) i jeśli zgłoszona jest wartość większa od 0, zostaje wyrzucony komunikat w syslogu. Dodanie znaku + do parametru wskaże smartd by traktował wartość z ostatniego skanowania jako bazową, czyli w moim przypadku 2.
Zapisujemy plik i restartujemy usługę:
# /etc/init.d/smartmontools
smartd[26236] Device: /dev/sda [SAT], state written to /var/lib/smartmontools/smartd.WDC_WD15EARS_00MVWB0-WD_WCAZA3607921.ata.state
smartd[26236] Device: /dev/sdb [SAT], state written to /var/lib/smartmontools/smartd.WDC_WD800JB_00JJA0-WD_WCAM91387401.ata.state
smartd[26236] smartd is exiting (exit status 0)
smartd[29402] smartd 6.2 2013-07-26 r3841 [x86_64-linux-3.12-3.slh.2-aptosid-amd64] (local build)
smartd[29402] Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
smartd[29402] Opened configuration file /etc/smartd.conf
smartd[29402] Drive: DEVICESCAN, implied '-a' Directive on line 23 of file /etc/smartd.conf
smartd[29402] Configuration file /etc/smartd.conf was parsed, found DEVICESCAN, scanning devices
smartd[29402] Device: /dev/sda, type changed from 'scsi' to 'sat'
smartd[29402] Device: /dev/sda [SAT], opened
smartd[29402] Device: /dev/sda [SAT], WDC WD15EARS-00MVWB0, S/N:WD-WCAZA3607921, WWN:5-0014ee-2b01eac3e, FW:51.0AB51, 1.50 TB
smartd[29402] Device: /dev/sda [SAT], found in smartd database: Western Digital Caviar Green (AF)
smartd[29402] Device: /dev/sda [SAT], is SMART capable. Adding to "monitor" list.
smartd[29402] Device: /dev/sda [SAT], state read from /var/lib/smartmontools/smartd.WDC_WD15EARS_00MVWB0-WD_WCAZA3607921.ata.state
smartd[29402] Device: /dev/sda, duplicate, ignored
smartd[29402] Monitoring 1 ATA and 0 SCSI devices
smartd[29402] Device: /dev/sda [SAT], state written to /var/lib/smartmontools/smartd.WDC_WD15EARS_00MVWB0-WD_WCAZA3607921.ata.state
smartd[29404] smartd has fork()ed into background mode. New PID=29404.
smartd[29404] file /var/run/smartd.pid written containing PID 29404
Jak widać nie ma już info o "2 Offline uncorrectable sectors".
Pisane w oparciu o własne doświadczenia oraz o http://smartmontools.sourceforge.net/badblockhowto.html.