Linux - Восстановление поврежденных блоков в массиве RAID1 с помощью GPT


20

Tl; dr: как мне исправить неисправный блок на 1 диске в массиве RAID1?

Но, пожалуйста, прочитайте все это о том, что я уже пробовал, и о возможных ошибках в моих методах. Я старался быть как можно более подробным, и я очень надеюсь получить отзывы

Это моя ситуация: у меня есть два диска по 2 ТБ (той же модели), настроенных в массиве RAID1, которым управляет mdadm. Около 6 месяцев назад я заметил первый плохой блок, когда SMART сообщил об этом. Сегодня я заметил больше, и сейчас пытаюсь это исправить.

Эта страница HOWTO, кажется, является единственной статьей, на которую все ссылаются, чтобы исправить плохие блоки, о которых сообщает SMART. Это отличная страница, полная информации, однако она довольно устарела и не соответствует моим конкретным настройкам. Вот как мой конфиг отличается:

  • Вместо одного диска я использую два диска в массиве RAID1. Один диск сообщает об ошибках, а другой в порядке. HOWTO написан только для одного диска, что вызывает различные вопросы, такие как «использовать ли я эту команду на дисковом устройстве или устройстве RAID»?
  • Я использую GPT, который не поддерживает fdisk. Вместо этого я использую 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узнать, используется ли блок (я использую устройство RAID, так как ему нужна файловая система EXT, это была одна из команд, которые смутили меня, поскольку я сначала не знал, следует ли мне использовать / 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, /dev/md0, и + -5 к номеру блока для поиска вокруг плохого блока. Все работает Я пожимаю плечами и продолжаю выполнять запись и синхронизацию (я использую / 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. Итак, как бы я мог исправить неисправный блок на 1 диске в массиве RAID1? Я уверен, что я не сделал что-то правильно ...

Спасибо за ваше время и терпение.


РЕДАКТИРОВАТЬ 1:

Я попытался запустить длинный SMART-тест, с тем же LBA, который показал плохой результат (единственное отличие - он сообщает, что осталось 30%, а не 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

Я также использовал 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

Больше команд и информации.

Я чувствую себя идиотом, забывшим включить это изначально. Это умные значения для /dev/sda. У меня есть 1 Current_Pending_Sector и 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

Согласно одному из ответов: казалось бы, я переключился seekи skipдля dd. Я использовал поиск, поскольку это то, что используется с HOWTO. Использование этой команды приводит ddк зависанию: # dd if = / dev / sda1 of = / dev / null bs = 4096 count = 1 skip = 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

Спасибо всем, кто помог. знак равно


Вы смогли прочитать блок, чтобы он не был поврежден. Следовательно, нет перераспределенных секторов. Я проверил ваш расчет блока фс, и это кажется законным. Когда я делал плохие перераспределения блоков, я обнаружил, что иногда умный короткий тест не сообщал правильно о нарушающем блоке. Тем временем вы можете запустить длинный автономный тест smartctl -t long /dev/sdaи посмотреть, изменится ли LBA первой ошибки.
Яри ​​Лааманен

1
Попробуйте /sbin/badblocks -sv /dev/sdaпроверить диск.
Джиппи

Я сделал оба предложения, и соответственно обновил пост. Все еще застряли. = /
блицман

Smartctl сообщает ненулевой счетчик Current_Pending_Sector? Offline_Unc корректируемый ненулевой?
Mgorven

Пожалуйста, добавьте статус массива к вопросу:sudo mdadm -D /dev/md0
psusi

Ответы:


20

Все эти ответы «тыкают в сектор», прямо скажем, безумны. Они рискуют (возможно скрыты) повреждением файловой системы. Если данные уже ушли, потому что на этом диске хранилась единственная копия, это было бы разумно. Но на зеркале есть отличная копия.

Вам просто нужно, чтобы mdraid вычистил зеркало. Он заметит плохой сектор и автоматически перезапишет его.

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

Вам нужно установить правильное устройство (например, md0 вместо mdX). Это займет некоторое время, так как это делает весь массив по умолчанию. В достаточно новом ядре вы можете сначала записать номера секторов в 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

Спасибо тебе за это. Я недавно вернулся к этой проблеме в надежде окончательно ее решить. Я записал в блок / dev / md0 и у меня были проблемы с файловой системой, но, к счастью, после нескольких часов террора и загрузки в оболочки восстановления все было исправлено без потерь данных. Сначала я попробую ваш метод, и, надеюсь, это избавит меня от ожидающего сектора. =)
блицманн

Как вы можете сказать, когда скраб завершен? Будет ли cat /sys/block/mdX/md/sync_actionчитать «простоя», когда закончите?
Джон Крам

@JonCram да, и вы можете наблюдать за статусом cat /proc/mdstatили, если хотите, /sys/…/sync_completed
написать

5

У меня просто была почти такая же проблема с массивом RAID1. Плохой сектор был в самом начале одного из разделов - сектор 16 в / dev / sdb2. Я следовал приведенным выше инструкциям: после проверки того, что логический блок 2 не используется файловой системой, и осторожности с поиском и пропуском dd, и обнулел 1 блок файловой системы:

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

Что это сделало? Это не исправило плохой сектор. Это, как теперь я знаю, связано с тем, что / dev / md0 не отображается непосредственно на / dev / sdb2, вы должны учитывать смещение RAID-данных! Подробнее об этом ниже. То, что он сделал, было маленькой, но потенциально разрушительной кашей в моей файловой системе. Оказывается, что логический блок 2 из / dev / md0 содержал полезные метаданные файловой системы и был в порядке на обоих дисках, пока я не скопировал обе копии, записав в / 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)

В этом случае смещение данных составляет 262144 сектора по 512 байт. Если вы удалите dd из / dev / md0 и сравните его с данными из необработанного раздела со смещением 131072K, вы обнаружите, что они совпадают. Так что в моем случае логический блок 2 (сектора 16-23) в / dev / sdb2 отсутствует даже в файловой системе; они находятся в суперблоке RAID, о котором вы можете прочитать здесь: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats - для версии 1.2 он состоит из 256 байтов + 2 байта на устройство в массиве все начинается с 4096 байт, поэтому в моем случае поврежденный сектор не использовался. Соответствующие секторы / dev / sdc2 (другая половина массива RAID1) равны нулю, поэтому я подумал, что было бы безопасно сделать это:

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

Это сработало!


ОП здесь. Спасибо за эту информацию. Когда эта проблема возникла у меня, я взял прыжок и обнул блок на уровне / dev / md0. Плохая идея, так как я случайно оборвал мою файловую систему. К счастью, после безбожного времени на ремонт все выглядело хорошо, без потерь данных. Но с начальной паникой я полностью забыл об этом посте. Недавно я установил свой сервер в моей новой квартире, и это еще одна вещь из моего списка задач, и я благодарю вас за понимание этой проблемы. Я обновлю ОП, когда найду немного больше. =)
блицманн

2

Если вы используете Debian, скорее всего, у вас есть работа в /etc/cron.d/mdadm. Это будет работать /usr/share/mdadm/checkarray --cron --all --idle --quiet первое воскресенье каждого месяца. Запустите это вручную, когда вы получите неисправимые аппаратные ошибки, чтобы ускорить переписывание.


Ну, когда вы запускаете его вручную, вы, вероятно, захотите остановиться --cron.
Дероберт

1

Вы перепутали свои ddаргументы. seekзаставляет его искать указанное смещение в выходных данных . Вы хотели skipблоки на входе .


Спасибо! Я обновил исходный пост, чтобы включить данные из этого. Если бы вы могли сказать мне, как исправить блок отсюда, я думаю, что предоставлю вам ответ. (Я не уверен, стоит ли мне писать напрямую /dev/sda1/или использовать /dev/md0для перезаписи блока) =)
blitzmann

@Ryan, запись в md0 должна быть способом, хотя sda1 также должен работать.
Псуси

0

Если у вас есть sw-raid1 и вы пишете данные одному из участников напрямую, у вас сразу же будет поврежден рейд. НЕ записывайте данные в sdaX или sdbX, если они являются частью MDX. Если вы пишете в mdX, у вас будут данные, скопированные на оба диска, если вы читаете из mdX, у вас будут данные, считанные с одного из дисков.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.