Linux - Memperbaiki blok buruk pada array RAID1 dengan GPT

20

Tl; dr: bagaimana cara memperbaiki blok buruk pada 1 disk dalam array RAID1?

Tapi tolong baca semua ini untuk apa yang sudah saya coba dan kemungkinan kesalahan dalam metode saya. Saya sudah mencoba sedetail mungkin, dan saya benar-benar berharap mendapat umpan balik

Ini adalah situasi saya: Saya memiliki dua disk 2TB (model yang sama) yang diatur dalam array RAID1 yang dikelola oleh mdadm. Sekitar 6 bulan yang lalu saya melihat blok buruk pertama ketika SMART melaporkannya. Hari ini saya lebih memperhatikan, dan sekarang berusaha memperbaikinya.

Halaman HOWTO ini tampaknya menjadi satu-satunya artikel yang ditautkan oleh semua orang untuk memperbaiki blok buruk yang dilaporkan SMART. Itu adalah halaman yang bagus, penuh dengan info, namun itu cukup usang dan tidak membahas pengaturan khusus saya. Inilah perbedaan konfigurasi saya:

  • Alih-alih satu disk, saya menggunakan dua disk dalam array RAID1. Satu disk melaporkan kesalahan sementara yang lain baik-baik saja. HOWTO ditulis dengan hanya satu disk dalam pikiran, yang memunculkan berbagai pertanyaan seperti 'apakah saya menggunakan perintah ini pada perangkat disk atau perangkat RAID'?
  • Saya menggunakan GPT, yang fdisk tidak mendukung. Saya telah menggunakan gdisk, dan saya berharap itu memberikan saya info yang sama yang saya butuhkan

Jadi, mari kita mulai. Inilah yang telah saya lakukan, namun sepertinya tidak berhasil. Silakan mengecek perhitungan dan metode saya untuk kesalahan. Kesalahan pelaporan disk adalah / 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

Dengan ini, kami mengumpulkan bahwa kesalahan berada pada LBA 3212761936. Mengikuti HOWTO, saya menggunakan gdisk untuk menemukan sektor awal yang akan digunakan kemudian dalam menentukan nomor blok (karena saya tidak dapat menggunakan fdisk karena tidak mendukung 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

Menggunakan tunefssaya menemukan blocksize menjadi 4096. Dengan menggunakan informasi ini dan perhitungan dari HOWTO, saya berkesimpulan bahwa blok yang dimaksud adalah ((3212761936 - 2048) * 512) / 4096 = 401594986.

HOWTO kemudian mengarahkan saya untuk debugfsmelihat apakah blok sedang digunakan (saya menggunakan perangkat RAID karena membutuhkan sistem file EXT, ini adalah salah satu perintah yang membingungkan saya karena saya tidak, pada awalnya, tahu apakah saya harus menggunakan / dev / sda atau / dev / md0):

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

Jadi blok 401594986 adalah ruang kosong, saya harus bisa menulis tanpa masalah. Namun, sebelum menulis kepadanya, saya mencoba memastikan bahwa itu memang tidak dapat dibaca:

# 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

Jika blok tidak dapat dibaca, saya tidak berharap ini berfungsi. Namun demikian. Saya ulangi menggunakan /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, /dev/md0, dan + -5 ke nomor blok untuk mencari di sekitar blok buruk. Semuanya bekerja. Saya mengangkat bahu dan melanjutkan menulis dan menyinkronkan (saya menggunakan / dev / md0 karena saya pikir memodifikasi satu disk dan tidak yang lain dapat menyebabkan masalah, dengan cara ini kedua disk menimpa blok buruk):

# 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 

Saya berharap bahwa menulis ke blok buruk akan memiliki disk menetapkan kembali blok ke yang baik, namun menjalankan tes SMART lain menunjukkan berbeda:

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

Kembali ke awal 1. Jadi pada dasarnya, bagaimana cara saya memperbaiki blok buruk pada 1 disk dalam array RAID1? Saya yakin saya tidak melakukan sesuatu dengan benar ...

Terima kasih atas waktu dan kesabaran Anda.


EDIT 1:

Saya sudah mencoba menjalankan tes SMART yang panjang, dengan LBA yang sama kembali sebagai buruk (satu-satunya perbedaan adalah melaporkan 30% tersisa daripada 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

Saya juga menggunakan badblock dengan output berikut. Outputnya aneh dan sepertinya tidak diformat, tapi saya mencoba untuk menguji angka-angka yang dikeluarkan sebagai blok tetapi debugfs memberikan kesalahan

# 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

Tidak yakin hendak kemana setelah ini. badblockspasti menemukan sesuatu, tetapi saya tidak yakin apa yang harus dilakukan dengan informasi yang disajikan ...


EDIT 2

Perintah dan info lebih lanjut.

Saya merasa seperti orang bodoh yang lupa untuk memasukkan ini pada awalnya. Ini adalah nilai SMART untuk /dev/sda. Saya memiliki 1 Current_Pending_Sector, dan 0 Offline_Ucorrectable.

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

Sebagai salah satu jawaban: sepertinya saya memang beralih seekdan skipuntuk dd. Saya menggunakan seek karena itulah yang digunakan dengan HOWTO. Menggunakan perintah ini menyebabkan ddhang: # dd if = / dev / sda1 dari = / dev / null bs = 4096 count = 1 skip = 401594986

Menggunakan blok di sekitar yang itu (..84, ..85, ..87, ..88) tampaknya berfungsi dengan baik, dan menggunakan / dev / sdb1 dengan blok 401594986membaca dengan baik juga (seperti yang diharapkan saat disk melewati pengujian SMART ). Sekarang, pertanyaan yang saya miliki adalah: Ketika menulis di daerah ini untuk menetapkan ulang blok, apakah saya menggunakan /dev/sda1atau /dev/md0? Saya tidak ingin menyebabkan masalah dengan array RAID dengan menulis langsung ke satu disk dan tidak memiliki pembaruan disk lainnya.

EDIT 3

Menulis ke blok secara langsung menghasilkan kesalahan sistem file. Saya telah memilih jawaban yang memecahkan masalah dengan cepat:

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

Terima kasih untuk semua pihak yang sudah membantu. =)

blitzmann
sumber
Anda bisa membaca blokir, sehingga tidak rusak. Karenanya, tidak ada sektor yang dialokasikan kembali. Saya memeriksa perhitungan blok fs Anda dan tampaknya sah. Ketika saya melakukan realokasi blok buruk, saya menemukan bahwa kadang-kadang tes singkat pintar tidak melaporkan blok menyinggung dengan benar. Sementara itu, Anda dapat menjalankan tes luring panjang, smartctl -t long /dev/sdadan melihat apakah LBA dari kesalahan pertama berubah.
Jari Laamanen
1
Coba /sbin/badblocks -sv /dev/sdaperiksa disk.
jippie
Saya telah melakukan kedua saran tersebut, dan telah memperbarui posnya. Masih macet. = /
blitzmann
Apakah smartctl melaporkan Current_Pending_Sector yang tidak nol? Apakah Offline_Uncorrectable non-zero?
mgorven
Silakan tambahkan status array ke pertanyaan:sudo mdadm -D /dev/md0
psusi

Jawaban:

20

Semua jawaban "poke the sector" ini, sejujurnya, gila. Mereka berisiko (mungkin tersembunyi) korupsi sistem file. Jika data sudah hilang, karena disk itu menyimpan satu-satunya salinan, itu akan masuk akal. Tetapi ada salinan yang sangat bagus di cermin.

Anda hanya perlu menggosok cermin. Ini akan melihat bad sector, dan menulis ulang secara otomatis.

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

Anda harus meletakkan perangkat yang tepat di sana (mis., Md0 bukan mdX). Ini akan memakan waktu cukup lama, seperti halnya seluruh array secara default. Pada kernel yang cukup baru, Anda dapat menulis nomor sektor untuk sync_min / sync_max terlebih dahulu, untuk membatasi hanya sebagian dari array.

Ini adalah operasi yang aman. Anda dapat melakukannya di semua perangkat mdraid Anda. Bahkan, Anda harus melakukannya di semua perangkat mdraid Anda, secara teratur. Distro Anda kemungkinan dikirim dengan cronjob untuk menangani hal ini, mungkin Anda perlu melakukan sesuatu untuk mengaktifkannya?


Script untuk semua perangkat RAID pada sistem

Beberapa waktu yang lalu, saya menulis skrip ini untuk "memperbaiki" semua perangkat RAID pada sistem. Ini ditulis untuk versi kernel lama di mana hanya 'perbaikan' yang akan memperbaiki bad sector; sekarang hanya melakukan pengecekan yang cukup (perbaikan masih berfungsi dengan baik pada kernel yang lebih baru, tetapi juga menyalin ulang / membangun kembali paritas, yang tidak selalu seperti yang Anda inginkan, terutama pada flash drive)

#!/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

Jika Anda ingin melakukan checkalih - alih repair, maka blok pertama (yang belum diuji) ini akan berfungsi:

    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
sumber
Terima kasih untuk ini. Saya baru-baru ini kembali ke masalah ini berharap akhirnya bisa menyelesaikannya. Saya memang menulis ke blok / dev / md0 dan saya memang memiliki masalah filesystem, tapi untungnya setelah beberapa jam teror dan boot ke shell pemulihan semua perbaikan tanpa dataloss. Saya akan mencoba metode Anda terlebih dahulu dan mudah-mudahan ini akan menyingkirkan saya dari sektor yang tertunda. =)
blitzmann
Bagaimana Anda tahu kapan scrub selesai? Akan cat /sys/block/mdX/md/sync_actionmembaca 'idle' saat selesai?
Jon Cram
@ JonCram ya, dan Anda dapat menonton status dengan cat /proc/mdstatatau jika Anda ingin skrip itu,/sys/…/sync_completed
derobert
5

Saya baru saja mengalami masalah yang hampir sama dengan array RAID1. Sektor buruk tepat di awal salah satu partisi - sektor 16 dari / dev / sdb2. Saya mengikuti petunjuk di atas: setelah memverifikasi bahwa blok logis 2 tidak digunakan oleh sistem file dan berhati-hati untuk mencari dan melewati jalan yang benar, dan memusatkan perhatian pada 1 blok sistem file:

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

Apa yang dilakukan ini? Itu tidak memperbaiki sektor yang buruk. Ini, sekarang saya tahu, karena / dev / md0 tidak memetakan langsung ke / dev / sdb2, Anda harus memperhitungkan RAID DATA OFFSET! Lebih lanjut tentang ini di bawah ini. Apa yang dilakukannya lakukan adalah kotoran kecil tetapi berpotensi merusak pada sistem file saya. Ternyata blok logis 2 dari / dev / md0 berisi metadata filesystem yang berguna dan baik-baik saja pada kedua disk, sampai saya membungkus kedua salinan dengan menulis ke / dev / md0. Untungnya, e2fsck -y / dev / md0 memperbaiki masalah (setelah memuntahkan jumlah output yang mengkhawatirkan) tanpa kehilangan data yang jelas. Hal yang dipelajari: jika debugfs icheck mengatakan 'block not found', itu tidak berarti sektor terkait tidak digunakan.

Kembali ke offset data: gunakan mdadm untuk menemukan offset seperti ini:

# 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)

Dalam hal ini, offset data adalah 262144 sektor dengan 512 byte. Jika Anda menemukan dari / dev / md0 dan membandingkannya dengan data dari partisi mentah dengan offset 131072K, Anda akan menemukannya cocok. Jadi dalam kasus saya, blok logis 2 (sektor 16--23) dari / dev / sdb2 bahkan tidak ada dalam sistem file; mereka berada di superblock RAID, yang dapat Anda baca di sini: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - untuk versi 1.2, ini terdiri dari 256 byte + 2 byte per perangkat dalam array , semua dimulai 4.096 byte, jadi dalam kasus saya, bad sector tidak digunakan. Sektor terkait dari / dev / sdc2 (bagian lain dari array RAID1) adalah nol jadi saya pikir akan lebih aman untuk melakukan ini:

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

Berhasil!

Samer
sumber
OP sini. Terimakasih atas informasinya. Ketika masalah ini muncul untuk saya, saya mengambil lompatan dan nol blok di tingkat / dev / md0. Gagasan buruk, karena saya juga menimpali sistem file saya. Syukurlah setelah memperbaiki jumlah yang tidak saleh, semua tampak baik tanpa dataloss. Tetapi dengan kepanikan awal saya benar-benar lupa tentang posting ini. Saya baru-baru mengatur server saya di apartemen baru saya, dan ini adalah salah satu hal di daftar todo saya sekali lagi, dan saya berterima kasih atas wawasan Anda tentang masalah ini. Saya akan memperbarui OP ketika saya mulai menggali lebih dalam. =)
blitzmann
2

Jika menjalankan debian Anda kemungkinan besar memiliki pekerjaan di /etc/cron.d/mdadm. Ini akan berjalan /usr/share/mdadm/checkarray --cron --all --idle --quiet minggu pertama setiap bulan. Jalankan itu secara manual ketika Anda mendapatkan kesalahan perangkat keras yang tidak dapat diperbaiki untuk mempercepat penulisan ulang.

Håkon Alstadheim
sumber
Nah, saat menjalankannya secara manual Anda mungkin ingin berhenti --cron.
derobert
1

Anda mencampuradukkan ddargumen Anda . seekmenyebabkannya mencari offset yang ditentukan dalam output . Anda ingin skipmemblokir input .

psusi
sumber
Terima kasih! Saya telah memperbarui posting asli untuk memasukkan data dari ini. Jika Anda bisa memberi tahu saya cara memperbaiki blok dari sini, saya pikir saya akan memberi Anda jawaban. (Saya tidak yakin apakah saya harus menulis langsung /dev/sda1/atau menggunakan /dev/md0untuk menimpa blok) =)
blitzmann
@Ryan, menulis ke md0 harus menjadi cara untuk pergi, meskipun sda1 juga harus bekerja.
psusi
0

Jika Anda memiliki sw-raid1 dan Anda menulis data ke salah satu anggota secara langsung, Anda akan memiliki serangan yang rusak segera. JANGAN menulis data ke sdaX atau sdbX jika mereka adalah bagian dari mdX. Jika Anda menulis ke mdX, Anda akan memiliki data yang disalin ke kedua drive, jika Anda membaca dari mdX, Anda akan meminta data membaca dari salah satu drive.

Jose Tavares
sumber