Linux - Naprawianie uszkodzonych bloków w macierzy RAID1 za pomocą GPT

20

Tl; dr: jak miałbym zająć się naprawieniem złego bloku na 1 dysku w macierzy RAID1?

Ale proszę przeczytaj całą tę rzecz, aby dowiedzieć się, co już próbowałem i możliwych błędów w moich metodach. Starałem się być jak najbardziej szczegółowy i naprawdę liczę na opinie

Oto moja sytuacja: mam dwa dyski 2 TB (ten sam model) ustawione w zarządzanej macierzy RAID1 mdadm. Około 6 miesięcy temu zauważyłem pierwszy zły blok, gdy SMART to zgłosił. Dzisiaj zauważyłem więcej i teraz próbuję to naprawić.

Ta strona HOWTO wydaje się być jedynym artykułem, do którego prowadzą linki, aby naprawić złe bloki raportowane przez SMART. To świetna strona, pełna informacji, jednak jest dość przestarzała i nie dotyczy mojej konkretnej konfiguracji. Oto jak różni się moja konfiguracja:

  • Zamiast jednego dysku używam dwóch dysków w macierzy RAID1. Jeden dysk zgłasza błędy, a drugi jest w porządku. HOWTO jest napisany z myślą tylko o jednym dysku, co rodzi różne pytania, takie jak „czy używam tego polecenia na urządzeniu dyskowym czy urządzeniu RAID”?
  • Używam GPT, którego fdisk nie obsługuje. Zamiast tego używam gdisk i mam nadzieję, że daje mi te same informacje, których potrzebuję

Przejdźmy do tego. Tak właśnie zrobiłem, jednak wydaje się, że nie działa. Prosimy o dokładne sprawdzenie moich obliczeń i metody pod kątem błędów. Błędy raportowania dysku to / dev / sda:

# smartctl -l selftest /dev/sda
smartctl 5.42 2011-10-20 r3458 [x86_64-linux-3.4.4-2-ARCH] (local build)
Copyright (C) 2002-11 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: read failure       90%     12169         3212761936

Dzięki temu możemy wywnioskować, że błąd dotyczy LBA 3212761936. Zgodnie z HOWTO używam gdisk, aby znaleźć sektor początkowy, który będzie później używany przy określaniu numeru bloku (ponieważ nie mogę użyć fdisk, ponieważ nie obsługuje GPT):

# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 3907029168 sectors, 1.8 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): CFB87C67-1993-4517-8301-76E16BBEA901
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048      3907029134   1.8 TiB     FD00  Linux RAID

Za pomocą tunefsznajduję rozmiar bloku 4096. Korzystając z tych informacji i obliczeń z HOWTO, dochodzę do wniosku, że omawiany blok jest ((3212761936 - 2048) * 512) / 4096 = 401594986.

HOWTO następnie każe mi debugfssprawdzić, czy blok jest w użyciu (używam urządzenia RAID, ponieważ wymaga ono systemu plików EXT, było to jedno z poleceń, które mnie pomyliły, ponieważ początkowo nie wiedziałem, czy powinienem użyć / dev / sda lub / dev / md0):

# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 401594986
Block 401594986 not in use

Zatem blok 401594986 jest pustą przestrzenią, powinienem móc nad nim pisać bez problemów. Przed napisaniem do niego staram się jednak upewnić, że nie można go odczytać:

# dd if=/dev/sda1 of=/dev/null bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000198887 s, 20.6 MB/s

Gdyby blok nie mógł zostać odczytany, nie spodziewałbym się, że to zadziała. Jednak tak jest. Powtarzam za pomocą /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0, i + -5 do numeru bloku szukać wokół zły blok. To wszystko działa. Wzruszam ramionami i kontynuuję zapis i synchronizację (używam / dev / md0, ponieważ pomyślałem, że modyfikowanie jednego dysku, a nie drugiego, może powodować problemy, w ten sposób oba dyski zastępują zły blok):

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000142366 s, 28.8 MB/s
# sync 

Spodziewałbym się, że zapis w złym bloku spowoduje, że dyski ponownie przypiszą blok do dobrego, jednak uruchomienie kolejnego testu SMART pokazuje inaczej:

# 1  Short offline       Completed: read failure       90%     12170         3212761936

Wróć do kwadratu 1. Więc w zasadzie, jak naprawić zły blok na 1 dysku w macierzy RAID1? Jestem pewien, że nie zrobiłem czegoś poprawnie ...

Dziękuję za poświęcony czas i cierpliwość.


EDYCJA 1:

Próbowałem przeprowadzić długi test SMART, przy czym ten sam LBA powraca jako zły (jedyna różnica polega na tym, że pozostało 30% zamiast 90%):

SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed: read failure       30%     12180         3212761936
# 2  Short offline       Completed: read failure       90%     12170         3212761936

Użyłem również badblocks z następującymi danymi wyjściowymi. Dane wyjściowe są dziwne i wydają się być źle sformatowane, ale próbowałem przetestować liczby wyprowadzane jako bloki, ale debugowanie powoduje błąd

# badblocks -sv /dev/sda
Checking blocks 0 to 1953514583
Checking for bad blocks (read-only test): 1606380968ne, 3:57:08 elapsed. (0/0/0 errors)
1606380969ne, 3:57:39 elapsed. (1/0/0 errors)
1606380970ne, 3:58:11 elapsed. (2/0/0 errors)
1606380971ne, 3:58:43 elapsed. (3/0/0 errors)
done
Pass completed, 4 bad blocks found. (4/0/0 errors)
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs:  open /dev/md0
debugfs:  testb 1606380968
Illegal block number passed to ext2fs_test_block_bitmap #1606380968 for block bitmap for /dev/md0
Block 1606380968 not in use

Nie jestem pewien, dokąd się udać. badblockszdecydowanie coś znalazłem, ale nie jestem pewien, co zrobić z prezentowanymi informacjami ...


EDYCJA 2

Więcej poleceń i informacji.

Czuję się jak idiota, który oryginalnie zapomniał o tym. To są wartości SMART dla /dev/sda. Mam 1 Current_Pending_Sector i 0 Offline_Uncorrectable.

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
  1 Raw_Read_Error_Rate     0x002f   100   100   051    Pre-fail  Always       -       166
  2 Throughput_Performance  0x0026   055   055   000    Old_age   Always       -       18345
  3 Spin_Up_Time            0x0023   084   068   025    Pre-fail  Always       -       5078
  4 Start_Stop_Count        0x0032   100   100   000    Old_age   Always       -       75
  5 Reallocated_Sector_Ct   0x0033   252   252   010    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x002e   252   252   051    Old_age   Always       -       0
  8 Seek_Time_Performance   0x0024   252   252   015    Old_age   Offline      -       0
  9 Power_On_Hours          0x0032   100   100   000    Old_age   Always       -       12224
 10 Spin_Retry_Count        0x0032   252   252   051    Old_age   Always       -       0
 11 Calibration_Retry_Count 0x0032   252   252   000    Old_age   Always       -       0
 12 Power_Cycle_Count       0x0032   100   100   000    Old_age   Always       -       75
181 Program_Fail_Cnt_Total  0x0022   100   100   000    Old_age   Always       -       1646911
191 G-Sense_Error_Rate      0x0022   100   100   000    Old_age   Always       -       12
192 Power-Off_Retract_Count 0x0022   252   252   000    Old_age   Always       -       0
194 Temperature_Celsius     0x0002   064   059   000    Old_age   Always       -       36 (Min/Max 22/41)
195 Hardware_ECC_Recovered  0x003a   100   100   000    Old_age   Always       -       0
196 Reallocated_Event_Count 0x0032   252   252   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   100   100   000    Old_age   Always       -       1
198 Offline_Uncorrectable   0x0030   252   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x0036   200   200   000    Old_age   Always       -       0
200 Multi_Zone_Error_Rate   0x002a   100   100   000    Old_age   Always       -       30
223 Load_Retry_Count        0x0032   252   252   000    Old_age   Always       -       0
225 Load_Cycle_Count        0x0032   100   100   000    Old_age   Always       -       77

# mdadm -D /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Thu May  5 06:30:21 2011
     Raid Level : raid1
     Array Size : 1953512383 (1863.01 GiB 2000.40 GB)
  Used Dev Size : 1953512383 (1863.01 GiB 2000.40 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Tue Jul  3 22:15:51 2012
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           Name : server:0  (local to host server)
           UUID : e7ebaefd:e05c9d6e:3b558391:9b131afb
         Events : 67889

    Number   Major   Minor   RaidDevice State
       2       8        1        0      active sync   /dev/sda1
       1       8       17        1      active sync   /dev/sdb1

Zgodnie z jedną z odpowiedzi: wydaje się, że zmieniłem seeki skipna dd. Korzystałem z wyszukiwania, ponieważ jest to używane w HOWTO. Użycie tego polecenia powoduje ddzawieszenie: # dd if = / dev / sda1 of = / dev / null bs = 4096 count = 1 skip = 401594986

Korzystanie z bloków wokół tego (..84, ..85, ..87, ..88) wydaje się działać dobrze, a używanie / dev / sdb1 z blokami 401594986również dobrze się sprawdza (zgodnie z oczekiwaniami, gdy dysk przeszedł testy SMART ). Teraz mam pytanie: czy pisząc po tym obszarze, aby ponownie przypisać bloki, czy używam /dev/sda1lub /dev/md0? Nie chcę powodować żadnych problemów z macierzą RAID, pisząc bezpośrednio na jednym dysku i nie mając aktualizacji drugiego dysku.

EDYCJA 3

Zapis do bloku spowodował bezpośrednio błędy systemu plików. Wybrałem odpowiedź, która szybko rozwiązała problem:

# 1  Short offline       Completed without error       00%     14211         -
# 2  Extended offline    Completed: read failure       30%     12244         3212761936

Dziękujemy wszystkim, którzy pomogli. =)

blitzmann
źródło
Czytałeś blok, więc nie jest uszkodzony. Dlatego nie ma przeniesionych sektorów. Sprawdziłem twoje obliczenia bloku fs i wydaje się to zgodne z prawdą. Kiedy dokonałem złych przesunięć bloków, dowiedziałem się, że czasami inteligentny krótki test nie zgłosił poprawnie nieprawidłowego bloku. W międzyczasie możesz uruchomić długi test offline smartctl -t long /dev/sdai sprawdzić, czy zmieni się LBA pierwszego błędu.
Jari Laamanen,
1
Spróbuj /sbin/badblocks -sv /dev/sdasprawdzić dysk.
jippie
Zrobiłem obie sugestie i odpowiednio zaktualizowałem post. Nadal utknąłem. = /
blitzmann
Czy smartctl zgłasza niezerową liczbę Current_Pending_Sector? Czy Offline_Uncorrectable jest niezerowy?
mgorven
Dodaj status tablicy do pytania:sudo mdadm -D /dev/md0
psusi

Odpowiedzi:

20

Wszystkie te odpowiedzi „szarpać sektor” są, szczerze mówiąc, szalone. Ryzykują (prawdopodobnie ukryte) uszkodzenie systemu plików. Gdyby dane już zniknęły, ponieważ na tym dysku przechowywana była jedyna kopia, byłoby to rozsądne. Ale na lustrze jest doskonale dobra kopia.

Musisz tylko mdraid wyszorować lustro. Zauważy zły sektor i przepisuje go automatycznie.

# echo 'check' > /sys/block/mdX/md/sync_action    # use 'repair' instead for older kernels

Musisz tam umieścić odpowiednie urządzenie (np. Md0 zamiast mdX). To zajmie trochę czasu, ponieważ domyślnie robi to cała tablica. W wystarczająco nowym jądrze możesz najpierw zapisać numery sektorów do sync_min / sync_max, aby ograniczyć go tylko do części tablicy.

To jest bezpieczna operacja. Możesz to zrobić na wszystkich swoich urządzeniach mdraid. W rzeczywistości powinieneś to robić regularnie na wszystkich urządzeniach mdraid. Twoja dystrybucja najprawdopodobniej jest wyposażona w cronjob, który sobie z tym poradzi, może musisz coś zrobić, aby to umożliwić?


Skrypt dla wszystkich urządzeń RAID w systemie

Jakiś czas temu napisałem ten skrypt, aby „naprawić” wszystkie urządzenia RAID w systemie. Zostało to napisane dla starszych wersji jądra, gdzie tylko „naprawa” naprawiłaby zły sektor; teraz samo sprawdzanie jest wystarczające (naprawa nadal działa dobrze na nowszych jądrach, ale także ponownie kopiuje / odbudowuje parzystość, co nie zawsze jest tym, czego chcesz, szczególnie na dyskach flash)

#!/bin/bash

save="$(tput sc)";
clear="$(tput rc)$(tput el)";
for sync in /sys/block/md*/md/sync_action; do
    md="$(echo "$sync" | cut -d/ -f4)"
    cmpl="/sys/block/$md/md/sync_completed"

    # check current state and get it repairing.
    read current < "$sync"
    case "$current" in
        idle)
            echo 'repair' > "$sync"
            true
            ;;
        repair)
            echo "WARNING: $md already repairing"
            ;;
        check)
            echo "WARNING: $md checking, aborting check and starting repair"
            echo 'idle' > "$sync"
            echo 'repair' > "$sync"
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac

    echo -n "Repair $md...$save" >&2
    read current < "$sync"
    while [ "$current" != "idle" ]; do
        read stat < "$cmpl"
        echo -n "$clear $stat" >&2
        sleep 1
        read current < "$sync"
    done
    echo "$clear done." >&2;
done

for dev in /dev/sd?; do
    echo "Starting offline data collection for $dev."
    smartctl -t offline "$dev"
done

Jeśli chcesz to zrobić checkzamiast tego repair, ten (nieprzetestowany) pierwszy blok powinien działać:

    case "$current" in
        idle)
            echo 'check' > "$sync"
            true
            ;;
        repair|check)
            echo "NOTE: $md $current already in progress."
            ;;
        *)
            echo "ERROR: $md in unknown state $current. ABORT."
            exit 1
            ;;
    esac
derobert
źródło
Dziękuję Ci za to. Niedawno wróciłem do tego problemu, mając nadzieję na jego rozwiązanie. Napisałem do bloku / dev / md0 i miałem problemy z systemem plików, ale na szczęście po kilku godzinach terroru i uruchomieniu się w powłokach odzyskiwania wszystko było naprawione bez utraty danych. Najpierw wypróbuję twoją metodę i mam nadzieję, że uwolni mnie to od oczekującego sektora. =)
blitzmann
Jak rozpoznać zakończenie szorowania? Czy cat /sys/block/mdX/md/sync_actionskończysz czytać „bezczynnie”?
Jon Cram
@JonCram tak, możesz obserwować status przez cat /proc/mdstatlub jeśli chcesz go /sys/…/sync_completed
napisać
5

Właśnie miałem taki sam problem z macierzą RAID1. Zły sektor był na początku jednej z partycji - sektor 16 / dev / sdb2. Postępowałem zgodnie z powyższymi instrukcjami: po sprawdzeniu, czy system logiczny 2 nie był używany przez system plików i uważając, aby uzyskać dd seek i pominąć właściwą drogę, wyzerowałem 1 blok systemu plików:

# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2

Co to zrobiło? Nie naprawił złego sektora. Teraz wiem, że ponieważ / dev / md0 nie mapuje bezpośrednio na / dev / sdb2, musisz wziąć pod uwagę PRZESUNIĘCIE DANYCH RAID! Więcej na ten temat poniżej. To, co zrobiła, to mała, ale potencjalnie niszcząca gówna w moim systemie plików. Okazuje się, że logiczny blok 2 / dev / md0 zawierał użyteczne metadane systemu plików i działał dobrze na obu dyskach, dopóki nie załamałem się na obu kopiach pisząc do / dev / md0. Na szczęście e2fsck -y / dev / md0 naprawił problem (po wyrzuceniu alarmującej ilości danych wyjściowych) bez widocznej utraty danych. Wyciągnięta lekcja: jeśli debugfs icheck mówi „nie znaleziono bloku”, niekoniecznie oznacza to, że odpowiednie sektory nie są używane.

Wróć do przesunięcia danych: użyj mdadm, aby znaleźć przesunięcie w następujący sposób:

# mdadm --examine /dev/sdb2
/dev/sdb2:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : ef7934b9:24696df9:b89ff03e:b4e5a05b
           Name : XXXXXXXX
  Creation Time : Sat Sep  1 01:20:22 2012
     Raid Level : raid1
   Raid Devices : 2

 Avail Dev Size : 1953241856 (931.38 GiB 1000.06 GB)
     Array Size : 976620736 (931.38 GiB 1000.06 GB)
  Used Dev Size : 1953241472 (931.38 GiB 1000.06 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : f3b5d515:446d4225:c2191fa0:9a9847b8

    Update Time : Thu Sep  6 12:11:24 2012
       Checksum : abb47d8b - correct
         Events : 54


    Device Role : Active device 0
    Array State : AA ('A' == active, '.' == missing)

W tym przypadku przesunięcie danych wynosi 262144 sektorów 512 bajtów. Jeśli dd z / dev / md0 i porównasz go z danymi z surowej partycji z przesunięciem 131072K, okaże się, że pasują do siebie. Więc w moim przypadku logiczny blok 2 (sektory 16--23) / dev / sdb2 nie ma nawet w systemie plików; znajdują się w superbloku RAID, o którym można przeczytać tutaj: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - w wersji 1.2 składa się z 256 bajtów + 2 bajty na urządzenie w tablicy , wszystkie zaczynają się od 4096 bajtów, więc w moim przypadku zły sektor nie został użyty. Odpowiednie sektory / dev / sdc2 (druga połowa macierzy RAID1) mają wartość zero, więc pomyślałem, że można to bezpiecznie zrobić:

# dd if=/dev/zero of=/dev/sdb2 bs=4096 count=1 seek=2

Zadziałało!

Samer
źródło
OP tutaj. Dziękuję za tę informację. Kiedy pojawił się ten problem, zrobiłem skok i wyzerowałem blok na poziomie / dev / md0. Zły pomysł, ponieważ zdarzyło mi się również, że zdemolowałem mój system plików. Na szczęście po bezbożnym czasie naprawy wszystko wydawało się dobrze bez utraty danych. Ale z początkową paniką całkowicie zapomniałem o tym poście. Niedawno zainstalowałem serwer w moim nowym mieszkaniu i jest to jedna z rzeczy na mojej liście rzeczy do zrobienia i dziękuję za wgląd w problem. Będę aktualizować OP, kiedy będę w pobliżu, aby kopać o tym trochę więcej. =)
blitzmann
2

Jeśli uruchamiasz debiana, najprawdopodobniej masz pracę w /etc/cron.d/mdadm. Odbędzie się to w /usr/share/mdadm/checkarray --cron --all --idle --quiet pierwszą niedzielę każdego miesiąca. Uruchom to ręcznie, gdy pojawią się nieusuwalne błędy sprzętowe, aby przyspieszyć przepisywanie.

Håkon Alstadheim
źródło
Cóż, uruchamiając go ręcznie, prawdopodobnie chcesz to przerwać --cron.
derobert
1

Zmieszałeś swoje ddargumenty. seekpowoduje, że szuka do określonego przesunięcia w danych wyjściowych . Chciałeś skipzablokować wejście .

psusi
źródło
Dziękuję Ci! Zaktualizowałem oryginalny post, aby zawierał dane z tego. Jeśli możesz mi powiedzieć, jak naprawić blok z tego miejsca, myślę, że udzielę ci odpowiedzi. (Nie jestem pewien, czy powinienem napisać bezpośrednio, /dev/sda1/czy użyć, /dev/md0aby zastąpić blok) =)
blitzmann
@Ryan, pisanie do md0 powinno być właściwą drogą, chociaż sda1 powinien również działać.
psusi
0

Jeśli masz sw-raid1 i zapisujesz dane bezpośrednio jednemu z członków, natychmiast otrzymasz uszkodzony raid. NIE zapisuj danych na sdaX lub sdbX, jeśli są one częścią mdX. Jeśli piszesz do mdX, będziesz mieć dane skopiowane na oba dyski, jeśli czytasz z mdX, będziesz mieć dane odczytane z jednego z dysków.

Jose Tavares
źródło