Короче говоря: как мне исправить плохой блок на 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
Дополнительные команды и информация.
Чувствую себя идиотом, забыв включить это изначально. Это значения SMART для /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
. Я использовал seek, так как это то, что используется в 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
Спасибо всем, кто помог. =)
решение1
Все эти ответы "poke the sector" откровенно говоря, безумны. Они рискуют (возможно, скрытым) повреждением файловой системы. Если бы данные уже исчезли, потому что на этом диске хранилась единственная копия, это было бы разумно. Но на зеркале есть совершенно хорошая копия.
Вам просто нужно, чтобы 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
решение2
У меня только что была почти такая же проблема с массивом RAID1. Плохой сектор находился в самом начале одного из разделов — секторе 16 /dev/sdb2. Я следовал инструкциям выше: убедившись, что логический блок 2 не используется файловой системой, и внимательно выполняя dd seek и skip в правильном направлении, обнулил 1 блок файловой системы:
# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2
Что это сделало? Это не исправило плохой сектор. Теперь я знаю, что это потому, что /dev/md0 не отображается напрямую на /dev/sdb2, вам нужно учитывать RAID DATA OFFSET! Подробнее об этом ниже. То, что это сделало, было небольшим, но потенциально разрушительным дерьмом в моей файловой системе. Оказывается, логический блок 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
Это сработало!
решение3
Если вы используете Debian, у вас, скорее всего, есть задание в /etc/cron.d/mdadm . Оно будет запускаться /usr/share/mdadm/checkarray --cron --all --idle --quiet
в первое воскресенье каждого месяца. Запускайте его вручную, когда у вас возникают неисправимые аппаратные ошибки, чтобы ускорить переписывание.
решение4
Если у вас есть sw-raid1 и вы пишете данные на один из участников напрямую, вы немедленно получите поврежденный raid. НЕ записывайте данные на sdaX или sdbX, если они являются частью mdX. Если вы пишете на mdX, вы скопируете данные на оба диска, если вы читаете с mdX, вы будете читать данные с одного из дисков.