md raid5: menerjemahkan angka sektor internal md ke offset

8

TL; Ringkasan DR : Terjemahkan nomor sektor md ke dalam offset di dalam /dev/mdXperangkat, dan bagaimana cara menyelidikinya xfs_db. Nomor sektor berasal dari sh->sectordalam linux/drivers/md/raid5.c:handle_parity_checks5().

Saya tidak tahu internal MD, jadi saya tidak tahu persis apa yang harus dilakukan dengan output dari printklogging yang saya tambahkan.

Offset ke perangkat komponen (untuk ddatau hex editor / viewer) juga akan menarik.

Saya kira saya harus menanyakan ini di milis Linux-raid. Apakah hanya pelanggan, atau bisakah saya memposting tanpa berlangganan?


Saya memiliki xfs langsung di atas MD RAID5 dari 4 disk di desktop saya (tidak ada LVM). Lulur baru-baru ini mendeteksi non-nol mismatch_cnt(8 pada kenyataannya, karena md beroperasi pada halaman 4kiB sekaligus).

Ini adalah RAID5, bukan RAID1 / RAID10 di mana mismatch_cnt! = 0 dapat terjadi selama operasi normal . (Tautan lain di bagian bawah halaman wiki ini mungkin berguna bagi sebagian orang.)

Saya hanya bisa membabi buta repair, tapi kemudian saya tidak tahu file mana untuk memeriksa kemungkinan korupsi, selain kehilangan kesempatan untuk memilih cara merekonstruksi mana. Jawaban Frostschutz pada pertanyaan serupa adalah satu-satunya saran yang saya temukan untuk melacak kembali perbedaan dalam sistem file. Ini rumit dan lambat, dan saya lebih suka menggunakan sesuatu yang lebih baik untuk mempersempitnya menjadi beberapa file terlebih dahulu.


Patch kernel untuk menambahkan logging

Anehnya, fitur cek md tidak melaporkan di mana kesalahan ditemukan . Saya menambahkan printkdi md / raid5.c untuk login sh->sectordi ifcabang yang bertahap mddev->resync_mismatchesdalamhandle_parity_checks5() (sepetak kecil yang diterbitkan pada github , awalnya didasarkan pada 4,5-RC4 dari kernel.org.) Untuk ini ok untuk penggunaan umum, mungkin akan perlu hindari membanjiri log dalam perbaikan dengan banyak ketidakcocokan (mungkin hanya login jika nilai baru resync_mismatches<1000?). Mungkin juga hanya masuk checkdan tidak repair.

Saya cukup yakin saya mencatat sesuatu yang bermanfaat (walaupun saya tidak tahu MD internal!), Karena fungsi yang sama mencetak nomor sektor dalam kasus penanganan kesalahan dariswitch .

Saya mengkompilasi kernel yang dimodifikasi dan mem-boot-nya, lalu menjalankan ulang pemeriksaan:

[  399.957203] md: data-check of RAID array md125
...
[  399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224    <-- custom log message
[25667.351869] md: md125: data-check done.

Sekarang saya tidak tahu persis apa yang harus dilakukan dengan nomor sektor itu. Apakah sh->sector * 512alamat linear di dalam /dev/md/t-r5(alias /dev/md125)? Apakah ini nomor sektor dalam setiap perangkat komponen (jadi ini mengacu pada tiga data dan satu sektor paritas)? Saya menduga yang terakhir, karena paritas-ketidakcocokan dalam RAID5 berarti N-1 sektor perangkat md berada dalam bahaya, diimbangi satu sama lain oleh unit stripe. Apakah sektor 0 merupakan permulaan dari perangkat komponen, atau apakah itu sektor setelah superblok atau semacamnya? Apakah ada informasi lebih lanjut handle_parity_checks5()yang seharusnya saya hitung / login?

Jika saya hanya ingin mendapatkan blok yang tidak cocok, apakah ini benar?

dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd  of=mmblock.3 bs=512 count=8 skip=4294708224  ## not a typo: my 4th component is a smaller full-disk

# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev"  skip="$1"  bs=512 count=8;done; }; sec_block 123456

Saya kira tidak, karena saya mendapatkan 4k nol dari keempat komponen serangan, dan 0^0 == 0, sehingga harus menjadi paritas yang benar, bukan?

Satu tempat lain yang pernah saya lihat menyebutkan menggunakan alamat sektor dalam md adalah untuk sync_mindan sync_max(dalam sysfs). Neil Brown di daftar linux-raid , dalam menanggapi pertanyaan tentang drive yang gagal dengan nomor sektor dari hdrecover, di mana Neil menggunakan nomor sektor disk penuh sebagai nomor sektor MD. Itu tidak benar kan? Bukankah angka sektor md relatif terhadap perangkat komponen (partisi dalam kasus itu), bukan perangkat lengkap yang menjadi bagian dari partisi?


sektor linear ke nama file XFS:

Sebelum menyadari bahwa nomor sektor md mungkin untuk komponen, bukan perangkat RAID, saya mencoba menggunakannya dalam read-only xfs_db:

Saran yang sangat singkat dari Dave Chinner tentang bagaimana menemukan bagaimana XFS menggunakan blok yang diberikan tampaknya tidak bekerja sama sekali untuk saya. (Saya akan mengharapkan semacam hasil, untuk beberapa sektor, karena jumlahnya tidak boleh melebihi akhir perangkat bahkan jika itu bukan sektor yang tidak cocok)

# xfs_db -r /dev/md/t-r5 
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n       # with or without -c 8
must run blockget first

Hah? Apa yang saya lakukan salah di sini? Saya kira ini harus menjadi pertanyaan terpisah. Saya akan mengganti ini dengan tautan jika / ketika saya bertanya atau menemukan jawaban untuk bagian ini di tempat lain.

RAID5 saya pada dasarnya idle, tanpa aktivitas tulis dan minimal baca (dan noatime, jadi baca tidak menghasilkan penulisan).


Banyak hal tambahan tentang pengaturan saya, tidak ada yang penting di sini

Banyak file saya adalah video atau data terkompresi lainnya yang memberikan cara efektif untuk mengetahui apakah data itu benar atau tidak (baik checksum internal dalam format file, atau hanya apakah itu diterjemahkan tanpa kesalahan). Itu akan membuat metode loopback read-only ini layak, setelah saya tahu file mana yang harus diperiksa. Saya tidak ingin menjalankan diff 4-arah dari setiap file di sistem file untuk menemukan ketidakcocokan pertama, ketika kernel memiliki informasi yang diperlukan saat memeriksa, dan dapat dengan mudah mencatatnya.


my /proc/mdstatuntuk array data massal saya:

md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
      7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/19 pages [0KB], 65536KB chunk

Ada di partisi pada tiga drive Toshiba 3TB, dan drive hijau (lambat) WD25EZRS non-partisi yang saya ganti dengan Toshiba lain. (Menggunakan mdadm --replaceuntuk melakukannya secara online tanpa celah dalam redundansi. Saya menyadari setelah satu salinan bahwa saya harus memeriksa kesehatan RAID sebelum dan sesudahnya, untuk mendeteksi masalah. Saat itulah saya mendeteksi ketidakcocokan. Mungkin sudah ada sejak lama. , sejak saya mengalami crash hampir setahun yang lalu, tapi saya tidak punya log lama dan mdadm sepertinya tidak mengirim email tentang ini secara default (Ubuntu 15.10).

Filesystem saya yang lain menggunakan perangkat RAID10f2 yang dibuat dari partisi sebelumnya pada tiga HD yang lebih besar (dan RAID0 untuk / var / tmp). RAID5 hanya untuk penyimpanan massal, bukan /homeatau /.

Drive saya baik-baik saja: jumlah kesalahan SMART adalah 0 semua penghitung blok buruk pada semua drive, dan tes mandiri SMART pendek + panjang berlalu.


duplikat dekat dari pertanyaan ini yang tidak memiliki jawaban:

Peter Cordes
sumber
Jika angka di printk Anda adalah relatif sektor ke array, maka Anda perlu membaginya dengan lebar garis dan mungkin menambahkan offset mulai untuk mengubahnya menjadi nomor sektor relatif ke perangkat komponen. iirc, jika Anda menggunakan format metadata mdadm yang tidak selalu memulai data pada nol offset, offset di mana ia mulai tercantum dalam output mdadm -E /dev/xxx.
psusi
Ingat juga bahwa meskipun Anda menemukan lokasi data dan dapat memverifikasi ketidakcocokan, dan memiliki cara untuk memeriksa integritas file yang rusak (jika data tersebut memang milik file; mungkin saja gratis space atau fs metadata), maka sangat mungkin dan bahkan kemungkinan bahwa paritasnya juga salah sehingga tidak ada jawaban yang mungkin Anda dapatkan dari menutup setiap drive data pada gilirannya akan benar.
psusi
@psusi: terima kasih, ya saya tahu itu mungkin bukan bagian dari file. Sulit untuk mengungkapkannya tanpa membuat kalimat saya benar-benar canggung. Poin menarik yang mungkin tidak ada rekonstruksi yang benar, ya itu mungkin. Either way, saya akan jauh lebih bahagia untuk mengetahui file mana yang harus diganti nama .damagedatau sesuatu, daripada hanya tahu mungkin ada file yang rusak di suatu tempat.
Peter Cordes

Jawaban:

2

Sektor TL; DR sh-> adalah jumlah sektor dalam disk fisik setelah dimulainya bagian data


Mendirikan

Berikut ini adalah pengaturan uji sederhana untuk menggambarkan:

  • / dev / raidme / rd [0-3], perangkat 2GB
  • / dev / md127 dibuat sebagai raid5 lebih dari 5 ini, init'd sebagai xfs dan diisi dengan data acak

Sekarang untuk memulai, dapatkan blok bukan nol dan timpa

# dd if=/dev/raidme/rd0 bs=1k count=1 skip=10240 | hexdump -C | head
...
# dd if=/dev/zero of=/dev/raidme/rd0 bs=1k count=1 seek=10240
...
# dd if=/dev/raidme/rd2 bs=1k count=1 skip=10240 | hexdump  -C | head
1024 bytes (1.0 kB, 1.0 KiB) copied, 8.6021e-05 s, 11.9 MB/s
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

Pastikan cache dm / md memerah dengan menghentikan / memasang kembali array, dan periksa:

# mdadm --stop /dev/md127
# mdadm --assemble /dev/md127 /dev/raidme/rd*
# echo check > /sys/class/block/md127/md/sync_action
# dmesg | tail
...
[ 1188.057900] md/raid:md127: check found mismatch at sector 16384

Blokir di disk

Oke, jadi pertama mari kita periksa 16384 cocok dengan apa yang kami tulis. Serangan saya memiliki garis 512k jadi saya memastikan saya menulis sesuatu yang selaras agar mudah dicocokkan, kami menulis di 1024*10240mis 0xa00000.

Tambalan Anda memberikan info 16384, satu hal yang perlu diperhatikan adalah bahwa data tidak dimulai pada 0:

# mdadm -E /dev/raidme/rd0 | grep "Data Offset"
    Data Offset : 4096 sectors

Jadi printf "%x\n" $(((4096+16384)*512))mengatakan itu 0xa00000juga. Baik.


Blokir di md

Sekarang untuk mendapatkan yang ada di ujung md, sebenarnya lebih mudah: itu hanya posisi yang diberikan di sektor kali number_of_stripesmisalnya untuk saya, saya punya 4 disk (3 +1) jadi 3 garis.

Di sini, itu berarti 16384*3*512mis 0x1800000. Saya mengisi disk dengan cukup baik sehingga mudah untuk memeriksa hanya membaca disk dan mencari 1r nol:

# dd if=/dev/md127 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00 00'
... some false positives...
01800000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
01800400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Blokir dalam xfs

Keren. Mari kita lihat di mana xfs berada sekarang. 16384*3is 49152(daddr mengambil nomor sektor):

# xfs_db -r /dev/md127
xfs_db> blockget -n
xfs_db> daddr 49152
xfs_db> blockuse -n
block 6144 (0/6144) type data inode 2052 d.1/f.1

Tentunya, angka nol ada di file itu:

# dd if=/mnt/d.1/f.1 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00'
...
03680000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
03680400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Jika kita menimpa file itu, nolnya akan ada di / dev / raidme / rd0 di offset yang benar juga (cukup lakukan dengan file lain). Jika Anda menulis di / dev / raidme / rd0 lagi (pastikan Anda menghentikan / memulai array lagi) maka nolnya kembali. Kelihatan bagus.

Namun ada satu masalah lagi, jika ukuran garis Anda sebesar milik saya di sini (512k), maka kami tidak memiliki satu blok untuk menangani tetapi 1,5MB dari data yang mungkin rusak ... Cukup sering itu akan berada dalam satu file, tetapi Anda perlu memeriksanya, kembali di xfs_db. Ingat inode sebelumnya adalah 2052.

xfs_db> inode 2052
xfs_db> bmap
data offset 0 startblock 256 (0/256) count 17536 flag 0
data offset 17536 startblock 122880 (0/122880) count 4992 flag 0
data offset 22528 startblock 91136 (0/91136) count 3072 flag 0

Satu blok berukuran 4096 byte di sini (lihat xfs_info), jadi 1.5MB kami adalah 384 blok. Segmen rusak kami adalah blok 6144 hingga 6528 - baik di dalam segmen pertama dari file ini.

Sesuatu yang lain untuk dilihat adalah mengekstraksi blok dengan tangan dan memeriksa di mana tepatnya checksum tidak cocok, yang diharapkan akan memberi Anda 3 potongan kecil untuk dilihat.


Terakhir tentang tambalan Anda, saya bukan md dev sendiri, tetapi sebagai pengguna raid5 mantan mdadm, saya akan sangat tertarik. Saya akan mengatakan itu sepadan dengan usaha untuk mendorongnya sedikit. Pembersihan yang Anda sebutkan mungkin berguna dan saya yakin para devs akan memiliki beberapa komentar setelah Anda mengirimkan tambalan, tetapi huh md perlu lebih bertele-tele tentang kesalahan ini!

Asmadeus
sumber
Huh, saya senang Anda menunjukkan posisi pada perangkat blok yang mendasarinya. Dalam kasus saya, printf '%#x\n' $(( (259072+4294708224 )*512 ))adalah 0x20000000000, yang jelas bukan suatu kebetulan. (Tepatnya itu adalah 2TiB. Saya menduga ada shenanigans dari grub-install atau semacam MBR). Saya tidak akan memperhatikan ini jika saya hanya melihat offset dalam perangkat MD untuk menemukan file yang terpengaruh. (BTW, %#xformat menambahkan 0xawalan untuk Anda.)
Peter Cordes
xfs_dbhanya mengatakan must run blockget first, meskipun saya baru saja melakukannya (persis seperti yang saya posting di pertanyaan), setelah mengikuti contoh Anda. Bahkan jika saya gunakan blockget -v -n -b 12884124672untuk memberikannya blok tertentu. Saya menggunakan dddan hexdumpmenemukan bahwa sebenarnya ada ketidakcocokan di blok itu. Tiga semuanya nol, dan yang keempat memiliki satu bit ditetapkan pada 1kiB ke dalam garis 512k. (Sangat mudah bahwa saya tidak perlu menemukan cara untuk benar-benar blok XOR untuk memeriksa redundansi.)
Peter Cordes
Jika saya menggunakan daddrpertama (sebelum blockget), saya tidak mendapatkan pesan kesalahan, hanya saja tidak ada output sama sekali dari blockget -v -ndan blockuse -v -n. Dalam hal ini penting, xfsprogs saya adalah 3.2.1ubuntu1, dan saya menggunakan Linux 4.2.0-36-generic (bukan kernel -rc patched saya). FS saya gunakan crc=1 isize=512, naming =version 2 bsize=4096 ascii-ci=0 ftype=1
Peter Cordes
Lagi pula, jawaban ini mengidentifikasi dengan benar lokasi blok yang tidak cocok pada perangkat komponen, dan pada perangkat md. Satu-satunya bagian yang tidak berfungsi adalah XFS block-> nama file bagian, yang merupakan pertanyaan terpisah. Secara teori saya bisa menggunakan find -exec xfs_bmap -vpl {} +untuk mencari file yang berisi blok yang dikenal.
Peter Cordes
1
Sayangnya saya tidak mengetahui cara apa pun untuk membuat xfs_db mengabaikan jurnal log (mis. Paksa blockget bahkan jika tidak 100% konsisten), atau untuk membuat kernel "flush" yang log sebagai umount / mount akan lakukan dan membuat xfs_db bahagia. .. Jadi ya, kecuali jika Anda ingin melakukan sesuatu, mungkin perlu menunggu sedikit sampai Anda dapat mengunggah. Terus perbarui saya dan jangan lupa mencoba upstream tambalan itu :)
Asmadeus