Некоторое время назад возникла задача построения достаточно вместительного массива для хранения оперативных инкрементальных бекапов. Причём тратить деньги особо не хотелось, а место было нужно. Решение было простым и достаточно удобным. Далее много текста.
За основу было взято шасси SuperChassis 825TQ-560LPB
В которое было вставлено 8 дисков Hitachi 1TB и контроллер LSI Logic SAS HBA SAS3081E-R. Мы заранее планировали схему без аппаратного рейда опираясь только на возможности ZFS.
Первая версия сервера на FreeBSD 7.2-STABLE прожила примерно около 3х месяцев, за это время отловились основные баги в виде ограничения используемой памяти vm.kmem_size и vfs.zfs.arc_max.
При недостатке выделяемой ядру памяти система падала в панику, при недостатке буферов arc_max очень сильно падала скорость работы. Для загрузки системы использовалась флешка размером 1GB, которая позволила спокойно менять версию системы простой заменой флешки с новой сборкой.
Схема построенного массива была основана на адресации по имени диска(устройства).
Далее по тексту будут вставки из dmesg и консольных команд работы.
В принципе всё более менее понятно. Есть контроллер, есть луны, есть диски, есть имена подключенных устройств к контроллеру.
Всё работает до тех пор пока не умирает один из дисков. У меня начал осыпаться седьмой диск и контроллер по timeout выкидывал его из массива. Причём уверенности в том, что посыпался сам диск у меня не было, потому что диски были абсолютно новыми и никаким нагрузкам не подвергались.
DFT от Hitachi ошибок не находила и говорила что всё в норме, только иногда подтормаживала. MHDD нашёл много секторов с временем доступа около 500 мс, после 50 таких секторов я диск просто поменял по гарантии.
Но диск это реально полбеды. Диск поборол, но вот проблемы пойманные при его сбоях заставили задуматься.
Проблема первая: Массив с нумерацией дисков не привязанной к лунам
ZFS в Solaris разрабатывалась с учётом привязки дисков к номерам контроллеров и лунам на этих контроллерах. В случае использования такой схемы учёта необходимо только заменить умерший диск и синхронизировать данные в массиве. В FreeBSD как и в Linux именование устройств обычно идёт прозрачное и не зависит от физического порта на контроллере. В этом на самом деле и заключается самая большая засада.
К примеру возьмём и вытащим из системы 5 диск, эмулируя аппаратный сбой на диске.
Всё отлично. Контроллер увидел, что у него пропал диск и пометил его как отсутствующий.
Можно вставить новый диск и синхронизировать массив. НО если Вы перезагрузите сервер, то
вас ждёт очень интересная картина(я уберу лишнюю информацию из квотинга dmesg, чтобы не перегружать текстом экран)
Что мы видим?
Мы видим что по сравнению с первым дампом dmesg, устройств стало 8 вместо 9 и флешка стала da7 вместо da8. ZFS начинает материться о том, что есть проблемы с чтением GPT меток и что всё плохо.
Zpool тупо развалился на глазах, так как нумерация дисков уехала на 1 вверх, что в свою очередь вызвало потерю массивом ориентиров для работы и путанице в метках дисков.
Обратите внимание, что у нас 2!!! диска da6. Всё это потому, что у нас есть физический диск определенный как da6 и присутствует GPT метка da6 на диске который раньше был da6.
теперь попробуем воткнуть диск который вытащили.
Диск определился, но стал da8. Мы конечно же можем попробовать перестроить массив, но ни к чему хорошему это не приведёт. Поэтому просто перегружаемся.
После перезагрузки zfs спокойно находит все диски, немного ругается в лог и продолжает работать.
resilver проходит практически безболезненно, так как у нас не было работы с данными на сломанном массиве.
В общем мы убедились, что такая схема не очень надёжна при автоматической нумерации дисков в контроллере. Хотя если количество дисков не меняется — их можно переставлять в произвольном порядке. Массив будет работать исправно.
Проблема вторая: geomlabel на дисках.
Дабы попытаться решить проблему с именованием дисков было решено попробовать пометить их метками и уже метки добавить в массив. При создании метки на диске — она пишется в конец диска, при инициализации диска система считывает метки и создаёт виртуальные устройства /dev/label/имяметки.
Массив живёт нормально, теперь мы выдёргиваем disk1 и откладываем в сторону.
Перегружаем сервер и смотрим в лог.
Но при всей ругани массив на поверку оказывается живой. с живой структурой и статусом DEGRADED, что намного лучше чем в первом случае.
Теперь мы зануляем диск который мы вытащили и вставим его обратно в систему.
Метка на диске записана в самом конце диска, поэтому штатное зануление начала диска нам ничем не поможет. придётся или нулить конец или просто диск целиком. Всё зависит от наличия у вас времени.
Даём новому диску метку «disk8» и пытаемся заменить «умерший» диск новым.
Система отказывается менять нам диск ссылаясь на его занятость. Заменить «умерший» диск можно только прямым именем устройства. Почему так сделано, я до конца не понял. Отбрасываем затею замены меток на новом диске и пробуем просто дать метку «disk1» новому диску.
Теперь нам нужно сказать, что диск у нас вернулся в строй.
Всё встаёт на свои места и после синхронизации можно сбросить статус пула на нормальный.
А вот тут начинается проблема. Так как метка диска сделанная glabel пишется в конец диска, то zfs в принципе не знает ничего о том, где она записана. И при полном заполнении диска перетирает эту метку. Диску в массиве присваивается физическое имя и мы возвращаемся к пункту 1 наших проблем.
Решение проблемы
Решение проблемы оказалось немного банальным и простым. Давным давно FreeBSD стала уметь делать GPT разделы на дисках больших объёмов. В FreeBSD 7.2 именование GPT разделов не работало и доступ к ним осуществлялся по прямому имени устройства /dev/da0p1(пример для первой партиции GPT)
В FreeBSD 8.0 в систему GPT меток было внесено изменение. И теперь GPT разделы можно именовать и обращаться к ним как к виртуальным устройствам через /dev/gpt/меткараздела.
Всё что нам реально необходимо сделать — это проименовать разделы на дисках и собрать из них массив. Как это сделать написано в ZFS Boot Howto которое очень быстро гуглится.
После создания GPT раздела по gpart show можно посмотреть где начинается и где заканчивается область данных на диске. Далее мы создаём этот раздел и даём ему метку «disk0».
Проделываем эту операцию для всех дисков в системе и собираем из полученных разделов массив.
Сервер спокойно переживает любые перезагрузки и перестановку дисков, а также их замену с той-же меткой. Скорость работы данного массива по сети достигает 70-80 мегабайт в секунду. Локальная скорость записи на массив в зависимости от заполняемости буферов доходит до 200 мегабайт в секунду.
PS: при использовании gpt меток натолкнулся на странный глюк, что система не видела новую метку на диске, но потом это само собой прошло.
PPS: энтузиастам которые пробуют запустить FreeBSD 8.0 с флешки(если это еще не починили) — пригодится вот такой dirty hack.
В новом USB стеке при загрузке ядра USB устройства не всегда определяются вовремя и возникает ошибка при монтировании разделов системы.
Данный хак выставляет в системе таймаут в 10 секунд для ожидания готовности USB накопителя.
PPPS: если будут вопросы — задавайте.
Настройки loader.conf для машины с 2мя гигабайтами памяти.
© Aborche 2009
За основу было взято шасси SuperChassis 825TQ-560LPB
В которое было вставлено 8 дисков Hitachi 1TB и контроллер LSI Logic SAS HBA SAS3081E-R. Мы заранее планировали схему без аппаратного рейда опираясь только на возможности ZFS.
Первая версия сервера на FreeBSD 7.2-STABLE прожила примерно около 3х месяцев, за это время отловились основные баги в виде ограничения используемой памяти vm.kmem_size и vfs.zfs.arc_max.
При недостатке выделяемой ядру памяти система падала в панику, при недостатке буферов arc_max очень сильно падала скорость работы. Для загрузки системы использовалась флешка размером 1GB, которая позволила спокойно менять версию системы простой заменой флешки с новой сборкой.
Схема построенного массива была основана на адресации по имени диска(устройства).
Далее по тексту будут вставки из dmesg и консольных команд работы.
mpt0: <LSILogic SAS/SATA Adapter> port 0x2000-0x20ff mem 0xdc210000-0xdc213fff,0xdc200000-0xdc20ffff irq 16 at device 0.0 on pci3
mpt0: [ITHREAD]
mpt0: MPI Version=1.5.20.0
mpt0: Capabilities: ( RAID-0 RAID-1E RAID-1 )
mpt0: 0 Active Volumes (2 Max)
mpt0: 0 Hidden Drive Members (14 Max)
da0 at mpt0 bus 0 scbus0 target 0 lun 0
da0: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da0: 300.000MB/s transfers
da0: Command Queueing enabled
da0: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da1 at mpt0 bus 0 scbus0 target 1 lun 0
da1: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da1: 300.000MB/s transfers
da1: Command Queueing enabled
da1: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da2 at mpt0 bus 0 scbus0 target 2 lun 0
da2: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da2: 300.000MB/s transfers
da2: Command Queueing enabled
da2: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da3 at mpt0 bus 0 scbus0 target 3 lun 0
da3: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da3: 300.000MB/s transfers
da3: Command Queueing enabled
da3: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da4 at mpt0 bus 0 scbus0 target 4 lun 0
da4: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da4: 300.000MB/s transfers
da4: Command Queueing enabled
da4: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da5 at mpt0 bus 0 scbus0 target 5 lun 0
da5: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da5: 300.000MB/s transfers
da5: Command Queueing enabled
da5: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da6 at mpt0 bus 0 scbus0 target 7 lun 0
da6: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da6: 300.000MB/s transfers
da6: Command Queueing enabled
da6: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da7 at mpt0 bus 0 scbus0 target 8 lun 0
da7: <ATA Hitachi HDE72101 A31B> Fixed Direct Access SCSI-5 device
da7: 300.000MB/s transfers
da7: Command Queueing enabled
da7: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
ugen3.2: <JetFlash> at usbus3
umass0: <JetFlash Mass Storage Device, class 0/0, rev 2.00/1.00, addr 2> on usbus3
umass0: SCSI over Bulk-Only; quirks = 0x0100
umass0:2:0:-1: Attached to scbus2
da8 at umass-sim0 bus 0 scbus2 target 0 lun 0
da8: <JetFlash Transcend 1GB 8.07> Removable Direct Access SCSI-2 device
da8: 40.000MB/s transfers
da8: 963MB (1972224 512 byte sectors: 64H 32S/T 963C)
Trying to mount root from ufs:/dev/ufs/FBSDUSB
В принципе всё более менее понятно. Есть контроллер, есть луны, есть диски, есть имена подключенных устройств к контроллеру.
backupstorage# zpool create storage raidz da0 da1 da2 da3 da4 da5 da6 da7
backupstorage# zpool status -v
pool: storage
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 ONLINE 0 0 0
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0
da7 ONLINE 0 0 0
errors: No known data errors
Всё работает до тех пор пока не умирает один из дисков. У меня начал осыпаться седьмой диск и контроллер по timeout выкидывал его из массива. Причём уверенности в том, что посыпался сам диск у меня не было, потому что диски были абсолютно новыми и никаким нагрузкам не подвергались.
DFT от Hitachi ошибок не находила и говорила что всё в норме, только иногда подтормаживала. MHDD нашёл много секторов с временем доступа около 500 мс, после 50 таких секторов я диск просто поменял по гарантии.
Но диск это реально полбеды. Диск поборол, но вот проблемы пойманные при его сбоях заставили задуматься.
Проблема первая: Массив с нумерацией дисков не привязанной к лунам
ZFS в Solaris разрабатывалась с учётом привязки дисков к номерам контроллеров и лунам на этих контроллерах. В случае использования такой схемы учёта необходимо только заменить умерший диск и синхронизировать данные в массиве. В FreeBSD как и в Linux именование устройств обычно идёт прозрачное и не зависит от физического порта на контроллере. В этом на самом деле и заключается самая большая засада.
К примеру возьмём и вытащим из системы 5 диск, эмулируя аппаратный сбой на диске.
backupstorage# camcontrol rescan all
Re-scan of bus 0 was successful
Re-scan of bus 1 was successful
Re-scan of bus 2 was successful
mpt0: mpt_cam_event: 0x16
mpt0: mpt_cam_event: 0x12
mpt0: mpt_cam_event: 0x16
mpt0: mpt_cam_event: 0x16
mpt0: mpt_cam_event: 0x16
(da4:mpt0:0:4:0): lost device
(da4:mpt0:0:4:0): Synchronize cache failed, status == 0x4a, scsi status == 0x0
(da4:mpt0:0:4:0): removing device entry
backupstorage# zpool status -v
pool: storage
state: DEGRADED
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage DEGRADED 0 0 0
raidz1 DEGRADED 0 0 0
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 REMOVED 0 0 0
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0
da7 ONLINE 0 0 0
Всё отлично. Контроллер увидел, что у него пропал диск и пометил его как отсутствующий.
Можно вставить новый диск и синхронизировать массив. НО если Вы перезагрузите сервер, то
вас ждёт очень интересная картина(я уберу лишнюю информацию из квотинга dmesg, чтобы не перегружать текстом экран)
da0 at mpt0 bus 0 scbus0 target 0 lun 0
da0: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da0: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da1 at mpt0 bus 0 scbus0 target 1 lun 0
da1: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da1: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da2 at mpt0 bus 0 scbus0 target 2 lun 0
da2: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da2: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da3 at mpt0 bus 0 scbus0 target 3 lun 0
da3: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da3: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da4 at mpt0 bus 0 scbus0 target 5 lun 0
da4: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da4: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da5 at mpt0 bus 0 scbus0 target 7 lun 0
da5: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da5: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
da6 at mpt0 bus 0 scbus0 target 8 lun 0
da6: <ATA Hitachi HDE72101 A31B> Fixed Direct Access SCSI-5 device
da6: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
SMP: AP CPU #1 Launched!
GEOM: da0: the primary GPT table is corrupt or invalid.
GEOM: da0: using the secondary instead -- recovery strongly advised.
GEOM: da1: the primary GPT table is corrupt or invalid.
GEOM: da1: using the secondary instead -- recovery strongly advised.
GEOM: da2: the primary GPT table is corrupt or invalid.
GEOM: da2: using the secondary instead -- recovery strongly advised.
GEOM: da3: the primary GPT table is corrupt or invalid.
GEOM: da3: using the secondary instead -- recovery strongly advised.
GEOM: da4: the primary GPT table is corrupt or invalid.
GEOM: da4: using the secondary instead -- recovery strongly advised.
GEOM: da5: the primary GPT table is corrupt or invalid.
GEOM: da5: using the secondary instead -- recovery strongly advised.
GEOM: da6: the primary GPT table is corrupt or invalid.
GEOM: da6: using the secondary instead -- recovery strongly advised.
ugen3.2: <JetFlash> at usbus3
umass0: <JetFlash Mass Storage Device, class 0/0, rev 2.00/1.00, addr 2> on usbus3
umass0: SCSI over Bulk-Only; quirks = 0x0100
umass0:2:0:-1: Attached to scbus2
da7 at umass-sim0 bus 0 scbus2 target 0 lun 0
da7: <JetFlash Transcend 1GB 8.07> Removable Direct Access SCSI-2 device
da7: 40.000MB/s transfers
da7: 963MB (1972224 512 byte sectors: 64H 32S/T 963C)
Trying to mount root from ufs:/dev/ufs/FBSDUSB
GEOM: da4: the primary GPT table is corrupt or invalid.
GEOM: da4: using the secondary instead -- recovery strongly advised.
GEOM: da5: the primary GPT table is corrupt or invalid.
GEOM: da5: using the secondary instead -- recovery strongly advised.
GEOM: da0: the primary GPT table is corrupt or invalid.
GEOM: da0: using the secondary instead -- recovery strongly advised.
GEOM: da1: the primary GPT table is corrupt or invalid.
GEOM: da1: using the secondary instead -- recovery strongly advised.
GEOM: da2: the primary GPT table is corrupt or invalid.
GEOM: da2: using the secondary instead -- recovery strongly advised.
GEOM: da3: the primary GPT table is corrupt or invalid.
GEOM: da3: using the secondary instead -- recovery strongly advised.
GEOM: da6: the primary GPT table is corrupt or invalid.
GEOM: da6: using the secondary instead -- recovery strongly advised.
GEOM: da4: the primary GPT table is corrupt or invalid.
GEOM: da4: using the secondary instead -- recovery strongly advised.
Что мы видим?
Мы видим что по сравнению с первым дампом dmesg, устройств стало 8 вместо 9 и флешка стала da7 вместо da8. ZFS начинает материться о том, что есть проблемы с чтением GPT меток и что всё плохо.
Zpool тупо развалился на глазах, так как нумерация дисков уехала на 1 вверх, что в свою очередь вызвало потерю массивом ориентиров для работы и путанице в метках дисков.
backupstorage# zpool status -v
pool: storage
state: UNAVAIL
status: One or more devices could not be used because the label is missing
or invalid. There are insufficient replicas for the pool to continue
functioning.
action: Destroy and re-create the pool from a backup source.
see: http://www.sun.com/msg/ZFS-8000-5E
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage UNAVAIL 0 0 0 insufficient replicas
raidz1 UNAVAIL 0 0 0 insufficient replicas
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 FAULTED 0 0 0 corrupted data
da5 FAULTED 0 0 0 corrupted data
da6 FAULTED 0 0 0 corrupted data
da6 ONLINE 0 0 0
Обратите внимание, что у нас 2!!! диска da6. Всё это потому, что у нас есть физический диск определенный как da6 и присутствует GPT метка da6 на диске который раньше был da6.
теперь попробуем воткнуть диск который вытащили.
backupstorage# camcontrol rescan all
Re-scan of bus 0 was successful
Re-scan of bus 1 was successful
Re-scan of bus 2 was successful
da8 at mpt0 bus 0 scbus0 target 4 lun 0
da8: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da8: 300.000MB/s transfers
da8: Command Queueing enabled
da8: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
GEOM: da8: the primary GPT table is corrupt or invalid.
GEOM: da8: using the secondary instead -- recovery strongly advised.
Диск определился, но стал da8. Мы конечно же можем попробовать перестроить массив, но ни к чему хорошему это не приведёт. Поэтому просто перегружаемся.
backupstorage# zpool status -v
pool: storage
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
da4 ONLINE 0 0 0
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0
da7 ONLINE 0 0 0
errors: No known data errors
После перезагрузки zfs спокойно находит все диски, немного ругается в лог и продолжает работать.
GEOM: da0: the primary GPT table is corrupt or invalid.
GEOM: da0: using the secondary instead -- recovery strongly advised.
GEOM: da1: the primary GPT table is corrupt or invalid.
GEOM: da1: using the secondary instead -- recovery strongly advised.
GEOM: da2: the primary GPT table is corrupt or invalid.
GEOM: da2: using the secondary instead -- recovery strongly advised.
GEOM: da3: the primary GPT table is corrupt or invalid.
GEOM: da3: using the secondary instead -- recovery strongly advised.
GEOM: da4: the primary GPT table is corrupt or invalid.
GEOM: da4: using the secondary instead -- recovery strongly advised.
GEOM: da5: the primary GPT table is corrupt or invalid.
GEOM: da5: using the secondary instead -- recovery strongly advised.
GEOM: da6: the primary GPT table is corrupt or invalid.
GEOM: da6: using the secondary instead -- recovery strongly advised.
GEOM: da7: the primary GPT table is corrupt or invalid.
GEOM: da7: using the secondary instead -- recovery strongly advised.
GEOM: da0: the primary GPT table is corrupt or invalid.
GEOM: da0: using the secondary instead -- recovery strongly advised.
GEOM: da2: the primary GPT table is corrupt or invalid.
GEOM: da2: using the secondary instead -- recovery strongly advised.
GEOM: da7: the primary GPT table is corrupt or invalid.
GEOM: da7: using the secondary instead -- recovery strongly advised.
resilver проходит практически безболезненно, так как у нас не было работы с данными на сломанном массиве.
GEOM: da0: the primary GPT table is corrupt or invalid.
GEOM: da0: using the secondary instead -- recovery strongly advised.
GEOM: da3: the primary GPT table is corrupt or invalid.
GEOM: da3: using the secondary instead -- recovery strongly advised.
====================
backupstorage# zpool status -v
pool: storage
state: ONLINE
scrub: resilver completed after 0h0m with 0 errors on Wed Nov 25 11:06:15 2009
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
da0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0 512 resilvered
da3 ONLINE 0 0 0 512 resilvered
da4 ONLINE 0 0 0
da5 ONLINE 0 0 0
da6 ONLINE 0 0 0 512 resilvered
da7 ONLINE 0 0 0 512 resilvered
errors: No known data errors
В общем мы убедились, что такая схема не очень надёжна при автоматической нумерации дисков в контроллере. Хотя если количество дисков не меняется — их можно переставлять в произвольном порядке. Массив будет работать исправно.
Проблема вторая: geomlabel на дисках.
Дабы попытаться решить проблему с именованием дисков было решено попробовать пометить их метками и уже метки добавить в массив. При создании метки на диске — она пишется в конец диска, при инициализации диска система считывает метки и создаёт виртуальные устройства /dev/label/имяметки.
backupstorage# zpool create storage raidz label/disk0 label/disk1 label/disk2 label/disk3 label/disk4 label/disk5 label/disk6 label/disk7
backupstorage# zpool status -v
pool: storage
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
label/disk0 ONLINE 0 0 0
label/disk1 ONLINE 0 0 0
label/disk2 ONLINE 0 0 0
label/disk3 ONLINE 0 0 0
label/disk4 ONLINE 0 0 0
label/disk5 ONLINE 0 0 0
label/disk6 ONLINE 0 0 0
label/disk7 ONLINE 0 0 0
errors: No known data errors
backupstorage# ls /dev/label/disk*
/dev/label/disk0 /dev/label/disk2 /dev/label/disk4 /dev/label/disk6
/dev/label/disk1 /dev/label/disk3 /dev/label/disk5 /dev/label/disk7
Массив живёт нормально, теперь мы выдёргиваем disk1 и откладываем в сторону.
Перегружаем сервер и смотрим в лог.
GEOM: da0: corrupt or invalid GPT detected.
GEOM: da0: GPT rejected -- may not be recoverable.
GEOM: da1: corrupt or invalid GPT detected.
GEOM: da1: GPT rejected -- may not be recoverable.
GEOM: da2: corrupt or invalid GPT detected.
GEOM: da2: GPT rejected -- may not be recoverable.
GEOM: da3: corrupt or invalid GPT detected.
GEOM: da3: GPT rejected -- may not be recoverable.
GEOM: da4: corrupt or invalid GPT detected.
GEOM: da4: GPT rejected -- may not be recoverable.
GEOM: da5: corrupt or invalid GPT detected.
GEOM: da5: GPT rejected -- may not be recoverable.
GEOM: da6: corrupt or invalid GPT detected.
GEOM: da6: GPT rejected -- may not be recoverable.
GEOM: label/disk0: corrupt or invalid GPT detected.
GEOM: label/disk0: GPT rejected -- may not be recoverable.
GEOM: label/disk2: corrupt or invalid GPT detected.
GEOM: label/disk2: GPT rejected -- may not be recoverable.
GEOM: label/disk3: corrupt or invalid GPT detected.
GEOM: label/disk3: GPT rejected -- may not be recoverable.
GEOM: label/disk4: corrupt or invalid GPT detected.
GEOM: label/disk4: GPT rejected -- may not be recoverable.
GEOM: label/disk5: corrupt or invalid GPT detected.
GEOM: label/disk5: GPT rejected -- may not be recoverable.
GEOM: label/disk6: corrupt or invalid GPT detected.
GEOM: label/disk6: GPT rejected -- may not be recoverable.
GEOM: label/disk7: corrupt or invalid GPT detected.
GEOM: label/disk7: GPT rejected -- may not be recoverable.
da7 at umass-sim0 bus 0 scbus2 target 0 lun 0
da7: <JetFlash Transcend 1GB 8.07> Removable Direct Access SCSI-2 device
da7: 40.000MB/s transfers
da7: 963MB (1972224 512 byte sectors: 64H 32S/T 963C)
Trying to mount root from ufs:/dev/ufs/FBSDUSB
GEOM: da0: corrupt or invalid GPT detected.
GEOM: da0: GPT rejected -- may not be recoverable.
GEOM: da1: corrupt or invalid GPT detected.
GEOM: da1: GPT rejected -- may not be recoverable.
GEOM: label/disk2: corrupt or invalid GPT detected.
GEOM: label/disk2: GPT rejected -- may not be recoverable.
GEOM: da2: corrupt or invalid GPT detected.
GEOM: da2: GPT rejected -- may not be recoverable.
GEOM: label/disk3: corrupt or invalid GPT detected.
GEOM: label/disk3: GPT rejected -- may not be recoverable.
GEOM: da3: corrupt or invalid GPT detected.
GEOM: da3: GPT rejected -- may not be recoverable.
GEOM: label/disk4: corrupt or invalid GPT detected.
GEOM: label/disk4: GPT rejected -- may not be recoverable.
GEOM: da4: corrupt or invalid GPT detected.
GEOM: da4: GPT rejected -- may not be recoverable.
GEOM: label/disk5: corrupt or invalid GPT detected.
GEOM: label/disk5: GPT rejected -- may not be recoverable.
GEOM: da5: corrupt or invalid GPT detected.
GEOM: da5: GPT rejected -- may not be recoverable.
Но при всей ругани массив на поверку оказывается живой. с живой структурой и статусом DEGRADED, что намного лучше чем в первом случае.
backupstorage# zpool status
pool: storage
state: DEGRADED
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: http://www.sun.com/msg/ZFS-8000-9P
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage DEGRADED 0 0 0
raidz1 DEGRADED 0 0 0
label/disk0 ONLINE 0 0 0
label/disk1 REMOVED 0 94 0
label/disk2 ONLINE 0 0 0
label/disk3 ONLINE 0 0 0
label/disk4 ONLINE 0 0 0
label/disk5 ONLINE 0 0 0
label/disk6 ONLINE 0 0 0
label/disk7 ONLINE 0 0 0
errors: No known data errors
====================
Теперь мы зануляем диск который мы вытащили и вставим его обратно в систему.
Метка на диске записана в самом конце диска, поэтому штатное зануление начала диска нам ничем не поможет. придётся или нулить конец или просто диск целиком. Всё зависит от наличия у вас времени.
mpt0: mpt_cam_event: 0x16
mpt0: mpt_cam_event: 0x12
mpt0: mpt_cam_event: 0x16
da8 at mpt0 bus 0 scbus0 target 1 lun 0
da8: <ATA Hitachi HDT72101 A31B> Fixed Direct Access SCSI-5 device
da8: 300.000MB/s transfers
da8: Command Queueing enabled
da8: 953869MB (1953525168 512 byte sectors: 255H 63S/T 121601C)
Даём новому диску метку «disk8» и пытаемся заменить «умерший» диск новым.
backupstorage# ls /dev/label/
disk0 disk2 disk3 disk4 disk5 disk6 disk7 disk8
backupstorage# zpool replace storage label/disk1 label/disk8
cannot replace label/disk1 with label/disk8: label/disk8 is busy
backupstorage# zpool replace -f storage label/disk1 label/disk8
cannot replace label/disk1 with label/disk8: label/disk8 is busy
Система отказывается менять нам диск ссылаясь на его занятость. Заменить «умерший» диск можно только прямым именем устройства. Почему так сделано, я до конца не понял. Отбрасываем затею замены меток на новом диске и пробуем просто дать метку «disk1» новому диску.
backupstorage# glabel label disk1 da8
Теперь нам нужно сказать, что диск у нас вернулся в строй.
backupstorage# zpool online storage label/disk1
backupstorage# zpool status
pool: storage
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: http://www.sun.com/msg/ZFS-8000-9P
scrub: resilver completed after 0h0m with 0 errors on Wed Nov 25 18:29:17 2009
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
label/disk0 ONLINE 0 0 0 6.50K resilvered
label/disk1 ONLINE 0 94 1 10.5K resilvered
label/disk2 ONLINE 0 0 0 6K resilvered
label/disk3 ONLINE 0 0 0 3.50K resilvered
label/disk4 ONLINE 0 0 0 6.50K resilvered
label/disk5 ONLINE 0 0 0 6.50K resilvered
label/disk6 ONLINE 0 0 0 5.50K resilvered
label/disk7 ONLINE 0 0 0 3K resilvered
errors: No known data errors
Всё встаёт на свои места и после синхронизации можно сбросить статус пула на нормальный.
А вот тут начинается проблема. Так как метка диска сделанная glabel пишется в конец диска, то zfs в принципе не знает ничего о том, где она записана. И при полном заполнении диска перетирает эту метку. Диску в массиве присваивается физическое имя и мы возвращаемся к пункту 1 наших проблем.
Решение проблемы
Решение проблемы оказалось немного банальным и простым. Давным давно FreeBSD стала уметь делать GPT разделы на дисках больших объёмов. В FreeBSD 7.2 именование GPT разделов не работало и доступ к ним осуществлялся по прямому имени устройства /dev/da0p1(пример для первой партиции GPT)
В FreeBSD 8.0 в систему GPT меток было внесено изменение. И теперь GPT разделы можно именовать и обращаться к ним как к виртуальным устройствам через /dev/gpt/меткараздела.
Всё что нам реально необходимо сделать — это проименовать разделы на дисках и собрать из них массив. Как это сделать написано в ZFS Boot Howto которое очень быстро гуглится.
backupstorage# gpart create -s GPT ad0
backupstorage# gpart add -b 34 -s 1953525101 -i 1 -t freebsd-zfs -l disk0 ad0
backupstorage# gpart show
=> 34 1953525101 da0 GPT (932G)
34 1953525101 1 freebsd-zfs (932G)
backupstorage# gpart show -l
=> 34 1953525101 da0 GPT (932G)
34 1953525101 1 disk0 (932G)
backupstorage# ls /dev/gpt
disk0
После создания GPT раздела по gpart show можно посмотреть где начинается и где заканчивается область данных на диске. Далее мы создаём этот раздел и даём ему метку «disk0».
Проделываем эту операцию для всех дисков в системе и собираем из полученных разделов массив.
backupstorage# zpool status -v
pool: storage
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
storage ONLINE 0 0 0
raidz1 ONLINE 0 0 0
gpt/disk0 ONLINE 0 0 0
gpt/disk1 ONLINE 0 0 0
gpt/disk2 ONLINE 0 0 0
gpt/disk3 ONLINE 0 0 0
gpt/disk4 ONLINE 0 0 0
gpt/disk5 ONLINE 0 0 0
gpt/disk6 ONLINE 0 0 0
gpt/disk7 ONLINE 0 0 0
errors: No known data errors
Сервер спокойно переживает любые перезагрузки и перестановку дисков, а также их замену с той-же меткой. Скорость работы данного массива по сети достигает 70-80 мегабайт в секунду. Локальная скорость записи на массив в зависимости от заполняемости буферов доходит до 200 мегабайт в секунду.
PS: при использовании gpt меток натолкнулся на странный глюк, что система не видела новую метку на диске, но потом это само собой прошло.
PPS: энтузиастам которые пробуют запустить FreeBSD 8.0 с флешки(если это еще не починили) — пригодится вот такой dirty hack.
Index: sys/kern/vfs_mount.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_mount.c,v
retrieving revision 1.308
diff -u -r1.308 vfs_mount.c
--- sys/kern/vfs_mount.c 5 Jun 2009 14:55:22 -0000 1.308
+++ sys/kern/vfs_mount.c 29 Sep 2009 17:08:25 -0000
@@ -1645,6 +1645,9 @@
options = NULL;
+ /* NASTY HACK: wait for USB sticks to appear */
+ pause("usbhack", hz * 10);
+
root_mount_prepare();
mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
В новом USB стеке при загрузке ядра USB устройства не всегда определяются вовремя и возникает ошибка при монтировании разделов системы.
Данный хак выставляет в системе таймаут в 10 секунд для ожидания готовности USB накопителя.
PPPS: если будут вопросы — задавайте.
Настройки loader.conf для машины с 2мя гигабайтами памяти.
vm.kmem_size=«1536M»
vm.kmem_size_max=«1536M»
vfs.zfs.arc_max=«384M»
© Aborche 2009