Linux - GPT를 사용하여 RAID1 어레이의 불량 블록 복구

Linux - GPT를 사용하여 RAID1 어레이의 불량 블록 복구

요약: RAID1 어레이의 디스크 1개에 있는 불량 블록을 수정하려면 어떻게 해야 합니까?

하지만 제가 이미 시도한 것과 제 방법에서 발생할 수 있는 오류에 대해서는 이 전체 내용을 읽어보시기 바랍니다. 최대한 자세히 설명하려고 노력했으며 피드백을 듣고 싶습니다.

이것이 제 상황입니다. 에서 관리하는 RAID1 어레이에 2개의 2TB 디스크(동일 모델)를 설정했습니다 mdadm. 약 6개월 전 SMART가 보고했을 때 첫 번째 불량 블록을 발견했습니다. 오늘 나는 더 많은 것을 발견했고 지금 그것을 고치려고 노력하고 있습니다.

이 HOWTO 페이지SMART가 보고하는 불량 블록을 수정하기 위해 모두가 링크하는 기사 중 하나인 것 같습니다. 정보가 가득한 훌륭한 페이지이지만 상당히 오래되었고 내 특정 설정을 다루지 않습니다. 내 구성이 다른 점은 다음과 같습니다.

  • 하나의 디스크 대신 RAID1 배열에 두 개의 디스크를 사용하고 있습니다. 한 디스크는 오류를 보고하지만 다른 디스크는 정상입니다. HOWTO는 하나의 디스크만을 염두에 두고 작성되었기 때문에 '이 명령을 디스크 장치에서 사용해야 합니까, 아니면 RAID 장치에서 사용해야 합니까?'와 같은 다양한 질문을 불러일으킵니다.
  • fdisk가 지원하지 않는 GPT를 사용하고 있습니다. 나는 대신 gdisk를 사용하고 있는데 그것이 나에게 필요한 것과 동일한 정보를 제공해주기를 바라고 있습니다.

그럼 그것에 대해 알아 보겠습니다. 이것이 내가 한 일이지만 작동하지 않는 것 같습니다. 내 계산과 방법에 오류가 있는지 다시 한번 확인하시기 바랍니다. 디스크 보고 오류는 /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

이를 통해 오류가 LBA 3212761936에 있다는 것을 수집합니다. HOWTO에 따라 gdisk를 사용하여 나중에 블록 번호를 결정할 때 사용할 시작 섹터를 찾습니다(fdisk는 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

사용하면 tunefs블록 크기가 4096. 이 정보와 HOWTO의 계산을 사용하여 문제의 블록이 이라는 결론을 내렸습니다 ((3212761936 - 2048) * 512) / 4096 = 401594986.

그런 다음 HOWTO에서는 debugfs블록이 사용 중인지 확인하도록 지시합니다. (저는 EXT 파일 시스템이 필요하기 때문에 RAID 장치를 사용합니다. 이것은 처음에 /를 사용해야 하는지 알지 못했기 때문에 혼란스러운 명령 중 하나였습니다. dev/sda 또는 /dev/md0):

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

따라서 블록 401594986은 빈 공간이므로 문제 없이 덮어쓸 수 있을 것입니다. 하지만 글을 쓰기 전에 실제로 읽을 수 없는지 확인하려고 노력합니다.

# 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

블록을 읽을 수 없다면 이것이 작동할 것이라고 기대하지 않을 것입니다. 그러나 그렇습니다. 불량 블록 주변을 검색하기 위해 블록 번호에 /dev/sda, /dev/sda1, /dev/sdb, /dev/sdb1, , +-5를 반복 사용합니다 . /dev/md0모두 작동합니다. 나는 어깨를 으쓱하고 계속해서 쓰기 및 동기화를 커밋합니다(한 디스크를 수정하고 다른 디스크는 수정하지 않으면 문제가 발생할 수 있다고 생각했기 때문에 /dev/md0을 사용합니다. 이렇게 하면 두 디스크가 모두 불량 블록을 덮어씁니다).

# 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 

불량 블록에 기록하면 디스크가 해당 블록을 좋은 블록에 다시 할당할 것으로 예상되지만 다른 SMART 테스트를 실행하면 다르게 표시됩니다.

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

1번으로 돌아가서 기본적으로 RAID1 어레이의 디스크 1개에 있는 불량 블록을 어떻게 수정합니까? 분명 뭔가 제대로 한 게 없는 것 같은데...

시간과 인내심을 가져주셔서 감사합니다.


편집 1:

동일한 LBA가 불량으로 반환되는 긴 SMART 테스트를 실행하려고 했습니다(유일한 차이점은 90%가 아닌 30%가 남아 있다는 것입니다).

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

또한 다음 출력과 함께 badblocks를 사용했습니다. 출력이 이상하고 형식이 잘못된 것 같습니다. 블록으로 출력된 숫자를 테스트해 보았지만 debugfs에서 오류가 발생합니다.

# 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

여기서 어디로 가야할지 잘 모르겠습니다. badblocks분명히 뭔가를 찾았지만 제시된 정보로 무엇을 해야 할지 모르겠습니다...


편집 2

추가 명령 및 정보.

나는 이것을 원래 포함하는 것을 잊어 버린 바보처럼 느껴집니다. 에 대한 SMART 값입니다 /dev/sda. Current_Pending_Sector가 1개이고 Offline_Uncorrrable이 0개 있습니다.

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

답변 중 하나에 따르면: seekskipfor 를 전환한 것 같습니다 dd. 나는 HOWTO에서 사용되는 탐색을 사용하고 있었습니다. 이 명령을 사용하면 dd중단됩니다. # dd if=/dev/sda1 of=/dev/null bs=4096 count=1 skim=401594986

해당 블록 주변의 블록(..84, ..85, ..87, ..88)을 사용하면 제대로 작동하는 것 같고 블록 읽기와 함께 /dev/sdb1을 사용하는 것도 401594986괜찮습니다(해당 디스크가 SMART 테스트를 통과했기 때문에 예상대로). ). 이제 제가 가지고 있는 질문은 다음과 같습니다. 블록을 재지정하기 위해 이 영역을 덮어쓸 때 /dev/sda1또는 를 사용해야 합니까 /dev/md0? 한 디스크에 직접 쓰고 다른 디스크는 업데이트하지 않음으로써 RAID 배열에 문제를 일으키고 싶지 않습니다.

편집 3

블록에 직접 쓰면 파일 시스템 오류가 발생합니다. 문제를 신속하게 해결하는 답변을 선택했습니다.

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

도움을 주신 모든 분들께 감사드립니다. =)

답변1

이 모든 "부문을 찌르는" 답변은 솔직히 말해서 미친 짓입니다. (숨겨져 있을 수도 있는) 파일 시스템이 손상될 위험이 있습니다. 데이터가 이미 사라진 경우 해당 디스크에 유일한 복사본이 저장되어 있으므로 합리적입니다. 하지만 거울에는 완벽하게 좋은 사본이 있습니다.

mdraid가 거울을 문지르도록 하면 됩니다. 불량 섹터를 발견하고 자동으로 다시 작성합니다.

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

거기에 올바른 장치를 넣어야 합니다(예: mdX 대신 md0). 기본적으로 전체 배열을 수행하므로 시간이 걸립니다. 충분히 새로운 커널에서는 먼저 sync_min/sync_max에 섹터 번호를 써서 배열의 일부로만 제한할 수 있습니다.

이것은 안전한 작업입니다. 모든 mdraid 장치에서 이 작업을 수행할 수 있습니다. 사실 당신은~해야 한다정기적으로 모든 mdraid 장치에서 수행하십시오. 귀하의 배포판은 이를 처리하기 위해 cronjob과 함께 제공될 가능성이 높습니다. 이를 활성화하기 위해 뭔가를 해야 할 수도 있습니까?


시스템의 모든 RAID 장치에 대한 스크립트

얼마 전에 저는 시스템의 모든 RAID 장치를 "복구"하기 위해 이 스크립트를 작성했습니다. 이는 '수리'만으로 불량 섹터를 수정할 수 있는 이전 커널 버전용으로 작성되었습니다. 이제는 확인하는 것만으로도 충분합니다. (최신 커널에서는 복구가 여전히 잘 작동하지만 패리티를 다시 복사/재구축하기도 합니다. 이는 특히 플래시 드라이브에서 항상 원하는 것은 아닙니다.)

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

check대신에 수행하려면 repair다음(테스트되지 않은) 첫 번째 블록이 작동해야 합니다.

    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

답변2

나는 RAID1 어레이와 거의 동일한 문제를 겪었습니다. 불량 섹터는 파티션 중 하나(/dev/sdb2의 섹터 16) 시작 부분에 있었습니다. 위의 지침을 따랐습니다. 논리 블록 2가 파일 시스템에서 사용되지 않는지 확인한 후 dd 탐색을 수행하고 올바른 방향으로 건너뛰고 1개의 파일 시스템 블록을 0으로 설정했습니다.

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

이게 무슨 짓을 한 거지? 불량 섹터를 수정하지 않았습니다. 이것은 /dev/md0이 /dev/sdb2에 직접 매핑되지 않기 때문에 RAID 데이터 오프셋을 고려해야 한다는 것을 이제 알고 있습니다! 이에 대한 자세한 내용은 아래에서 확인하세요. 그것이 한 일은 내 파일 시스템에 작지만 잠재적으로 파괴적인 똥이었습니다. /dev/md0의 논리 블록 2에는 유용한 파일 시스템 메타데이터가 포함되어 있었고 두 디스크 모두 괜찮았습니다.둘 다/dev/md0에 기록하여 복사합니다. 운 좋게도 e2fsck -y /dev/md0은 눈에 띄는 데이터 손실 없이 문제를 해결했습니다(놀라운 양의 출력을 뿜어낸 후). 교훈: debugfs icheck에 '블록을 찾을 수 없음'이라고 표시되면 반드시 해당 섹터가 사용되지 않는다는 의미는 아닙니다.

데이터 오프셋으로 돌아가서 다음과 같이 mdadm을 사용하여 오프셋을 찾으세요.

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

이 경우 데이터 오프셋은 512바이트의 262144개 섹터입니다. /dev/md0에서 dd를 하고 오프셋이 131072K인 원시 파티션의 데이터와 비교하면 일치하는 것을 찾을 수 있습니다. 따라서 내 경우에는 /dev/sdb2의 논리 블록 2(섹터 16-23)가 파일 시스템에도 없습니다. RAID 슈퍼블록에 있으며 여기에서 읽을 수 있습니다. https://raid.wiki.kernel.org/index.php/RAID_superblock_formats- 버전 1.2의 경우 256바이트 + 배열의 장치당 2바이트로 구성되며 모두 4096바이트부터 시작하므로 제 경우에는 배드 섹터가 사용되지 않았습니다. /dev/sdc2(RAID1 배열의 나머지 절반)의 해당 섹터는 0이므로 이렇게 하는 것이 안전할 것이라고 생각했습니다.

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

효과가 있었어요!

답변3

데비안을 실행한다면 /etc/cron.d/mdadm에 작업이 있을 가능성이 높습니다. /usr/share/mdadm/checkarray --cron --all --idle --quiet 매월 첫째주 일요일에 진행됩니다 . 수정할 수 없는 하드웨어 오류가 발생하면 수동으로 실행하여 재작성을 신속하게 처리하세요.

답변4

sw-raid1이 있고 구성원 중 한 명에게 직접 데이터를 쓰는 경우 즉시 손상된 raid가 발생합니다. mdX의 일부인 경우 sdaX 또는 sdbX에 데이터를 쓰지 마십시오. mdX에 쓰면 데이터가 두 드라이브 모두에 ​​복사되고, mdX에서 읽으면 드라이브 중 하나에서 데이터가 읽혀집니다.

관련 정보