설정

설정

핵심요약, DR 요약: md 섹터 번호를 장치 내 오프셋으로 변환 /dev/mdX하고 조사하는 방법 xfs_db. sh->sector에서 섹터 번호linux/drivers/md/raid5.c:handle_parity_checks5().

printkMD 내부를 이해하지 못해서 추가한 로깅의 출력을 어떻게 처리해야 할지 모르겠습니다 .

구성 요소 장치( dd16진수 편집기/뷰어용)의 오프셋도 흥미롭습니다.

나는 Linux-raid 메일링 리스트에 이 질문을 올려야겠다고 생각했습니다. 구독자 전용인가요, 아니면 구독하지 않고도 게시할 수 있나요?


내 xfs는 데스크탑(LVM 없음)에 있는 4개 디스크의 MD RAID5 바로 위에 있습니다. 가장 최근의 정리에서는 0이 아닌 값 mismatch_cnt(md가 한 번에 4kiB 페이지에서 실행되므로 실제로는 8)을 감지했습니다.

RAID1/RAID10이 아닌 RAID5입니다.여기서 mismatch_cnt!= 0은 정상 작동 중에 발생할 수 있습니다.. (추가링크는 하단에이 위키 페이지어떤 사람들에게는 유용할 수도 있습니다. )

맹목적으로 이 작업을 수행할 수 있지만 repair다시 빌드하는 방법을 선택할 기회를 잃는 것 외에도 어떤 파일이 손상되었는지 확인해야 할지 알 수 없습니다. 비슷한 질문에 대한 Frostschutz의 답변이것이 파일 시스템 차이점을 추적하기 위해 제가 찾은 유일한 제안입니다. 번거롭고 느리기 때문에 차라리 더 나은 것을 사용하여 먼저 몇 개의 파일로 범위를 좁히는 것이 좋습니다.


커널 패치에 로깅이 추가되었습니다.

이상한 점은,md의 확인 기능은 오류가 발견된 위치를 보고하지 않습니다.. printkmd/raid5.c에 sh->sector증가분 로깅을 위한 if분기를 추가 했습니다.mddev->resync_mismatcheshandle_parity_checks5()(작은 패치github에 게시, 원래 kernel.org의 4.5-rc4를 기반으로 합니다. ) 일반적인 용도로 사용할 수 있도록 하려면 수정 사항에서 큰 불일치로 인해 로그가 넘쳐나는 것을 방지해야 할 수도 있습니다(아마도 resync_mismatches새 값이 < 1000인 경우에만 로깅할까요?). check대신 for 를 기록하는 것도 가능합니다 repair.

동일한 함수가 섹터 번호를 인쇄하기 때문에 유용한 정보를 기록하고 있다고 확신합니다(MD 내부를 모르더라도!).오류 처리의 경우switch.

수정된 커널을 컴파일하고 부팅한 다음 검사를 다시 실행했습니다.

[  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.

이제 해당 섹터 번호로 무엇을 해야할지 모르겠습니다. 거기에 sh->sector * 512선형 주소 /dev/md/t-r5(일명 )가 있습니까? /dev/md125각 구성 장치 내의 섹터 번호입니까(따라서 3개의 데이터 섹터와 1개의 패리티 섹터를 나타냄)? 내 추측은 후자입니다. RAID5의 패리티 불일치는 md 장치의 N-1 섹터가 스트라이프 단위로 서로 오프셋되어 위험에 처해 있음을 의미하기 때문입니다. 섹터 0은 구성 요소 장치의 시작 부분입니까, 아니면 슈퍼 블록 이후의 섹터입니까, 아니면 다른 섹터입니까? handle_parity_checks5()더 많은 정보를 계산/기록해야 합니까?

일치하지 않는 청크만 얻으려는 경우 이것이 맞습니까?

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

네 개의 레이드 구성 요소 모두에서 4,000개의 0을 얻었기 때문에 그렇지 않을 것 같습니다 0^0 == 0. 그러면 이것이 올바른 패리티여야 합니다. 그렇죠?

sync_minmd에서 섹터 주소를 사용하는 것은 and sync_max(sysfs에서) 라는 것을 다른 곳에서 언급한 것을 보았습니다 .Neil Brown은 linux-raid 목록에 있습니다., 섹터 번호의 출처인 실패한 드라이브에 대한 질문에 hdrecoverNeil은 전체 디스크 섹터 번호를 MD 섹터 번호로 사용했습니다. 이게 맞지 않나요? md 섹터 번호는 파티션이 속한 전체 장치가 아닌 구성 요소 장치(이 경우 파티션)를 기준으로 하지 않습니까?


선형 섹터를 XFS 파일 이름으로:

md 섹터 번호가 아마도 RAID 장치가 아닌 구성 요소에 대한 것이라는 것을 깨닫기 전에 읽기 전용 모드에서 사용해 보았습니다 xfs_db.

Dave Chinner의 매우 간단한 조언XFS가 특정 블록을 사용하는 방법을 알아내는 방법에 대한 내용은 나에게 전혀 작동하지 않는 것 같습니다. (일부 섹터에서는 확실한 결과를 기대하고 있습니다. 불일치 섹터가 아니더라도 숫자가 장치 끝을 넘으면 안 되기 때문입니다.)

# 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

음? 내가 여기서 뭘 잘못하고 있는 걸까? 이건 별개의 질문이 되어야 할 것 같아요. 이 섹션에 대한 답변을 다른 곳에서 묻거나 찾으면 링크로 대체하겠습니다.

내 RAID5는 기본적으로 쓰기 활동이 없고 읽기가 최소화된 유휴 상태입니다( noatime따라서 읽기는 쓰기를 생성하지 않습니다).


내 설정에 대한 추가 정보, 여기서는 중요하지 않습니다.

내 파일 중 상당수는 비디오 또는 기타 압축 데이터이며 데이터가 올바른지(파일 형식의 내부 체크섬 또는 디코딩에 오류가 없는지) 알 수 있는 효율적인 방법을 제공합니다. 그러면이 읽기 전용 루프백 방법확인해야 할 파일을 알고 나면 작동합니다. 그러나 커널이 확인하고 쉽게 기록할 때 필요한 정보가 있을 때 불일치를 찾기 위해 파일 시스템의 모든 파일에 대해 먼저 4방향 diff를 실행하고 싶지 않습니다.


/proc/mdstat대량 데이터 배열:

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

Toshiba 3TB 드라이브 3개로 구성된 파티션에 있었고, 파티션되지 않은 WD25EZRS 친환경 전원(느린) 드라이브를 다른 Toshiba 드라이브로 교체했습니다. (사용mdadm --replace중복된 공백 없이 온라인으로 완료됩니다. 복사한 후 문제를 찾기 전과 후에 RAID 상태를 확인해야 한다는 것을 깨달았습니다. 그때 나는 불일치를 발견했습니다. 약 1년 전에 충돌이 발생했지만 오래된 로그가 없고 mdadm은 기본적으로 이에 대한 이메일을 보내지 않는 것 같습니다(Ubuntu 15.10).

내 다른 파일 시스템은 3개의 대형 HD(/var/tmp에 대한 RAID0과 함께)의 이전 파티션으로 구성된 RAID10f2 장치에 있습니다. RAID5는 /homeOR 이 아닌 대용량 저장소에만 사용됩니다 /.

내 드라이브에서는 모든 것이 정상입니다. 모든 불량 블록 카운터는 모든 드라이브에서 SMART 오류 개수가 0이고 단기+장기 SMART 자체 테스트를 통과했습니다.


이 질문은 거의 중복되지만 답변이 없습니다.

답변1

긴 이야기 짧게sh->섹터는 데이터 세그먼트가 시작된 후 물리적 디스크의 섹터 수입니다.


설정

설명하기 위한 간단한 테스트 설정은 다음과 같습니다.

  • /dev/raidme/rd[0-3], 2GB 장치
  • /dev/md127은 이 5개에서 raid5로 생성되고 xfs로 초기화되며 임의의 데이터로 채워집니다.

이제 시작하려면 0이 아닌 블록을 가져와서 덮어쓰세요.

# 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

어레이를 중지/재구성하여 dm/md 캐시를 플러시하고 다음을 확인하십시오.

# 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

디스크의 블록

좋아요, 먼저 16384가 우리가 쓴 것과 일치하는지 확인해 보겠습니다. 내 공격대에는 512k 스트라이프가 있으므로 쉽게 일치시킬 수 있도록 몇 가지 정렬 항목을 작성했는지 확인 1024*10240했습니다 0xa00000.

패치는 info 를 제공합니다 16384. 한 가지 주목할 점은 데이터가 0에서 시작하지 않는다는 것입니다.

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

그게 printf "%x\n" $(((4096+16384)*512))다야 0xa00000. 좋아요


md의 블록

이제 md 측의 위치를 ​​얻는 것이 실제로 더 쉽습니다. 섹터 시간에 지정된 위치일 뿐입니다 number_of_stripes. 예를 들어 제 경우에는 4개의 디스크(3+1)가 있으므로 3개의 스트라이프가 있습니다.

여기서는 16384*3*512다음을 0x1800000의미합니다 . 디스크를 잘 채웠기 때문에 디스크를 읽고 1,000개의 0을 찾는 것만으로도 쉽게 확인할 수 있습니다.

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

xfs의 블록

시원한. 이제 xfs의 위치를 ​​살펴보겠습니다. 16384*349152(daddr이 섹터 번호를 사용함):

# 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

파일에 0이 있다는 것은 의심의 여지가 없습니다.

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

해당 파일을 덮어쓰면 /dev/raidme/rd0의 올바른 오프셋에 있는 0도 사라집니다(다른 파일에 추가하면 됩니다). /dev/raidme/rd0에 다시 쓰면(배열을 다시 중지/시작해야 함) 0이 다시 나타납니다. 좋아 보인다.

하지만 한 가지 문제는 스트라이프 크기가 ​​내 것(512k)만큼 크다면 처리할 단일 블록이 없고 가능한 데이터 중 1.5MB만 손상된다는 것입니다. 일반적으로 이는 단일 파일에 표시되지만 확인하려면 xfs_db로 돌아가야 합니다. 이전 inode는 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

여기서 블록 크기는 4096바이트(참고자료 참조 xfs_info)이므로 1.5MB는 384블록입니다. 손상된 세그먼트는 파일의 첫 번째 세그먼트 내 블록 6144~6528입니다.

주목해야 할 다른 사항은 수동으로 청크를 추출하고 체크섬이 일치하지 않는 위치를 정확히 확인하는 것입니다. 그러면 살펴볼 3개의 작은 청크가 제공될 것입니다.


마지막으로 패치와 관련하여 저는 md 개발자는 아니지만 이전 mdadm raid5 사용자로서 매우 관심이 있습니다. 확실히 노력할만한 가치가 있다고 말하고 싶습니다. 귀하가 언급한 정리는 유용할 수 있으며 패치를 제출하면 개발자가 몇 가지 의견을 제시할 것이라고 확신합니다. 하지만 MD는 이러한 버그에 대해 더 자세히 설명해야 합니다!

관련 정보