DIR825. USB-накопитель под «ОСь».

DIR825. USB-накопитель под «ОСь».

Немного лирического отступления … «Покопавшись» с фонерой — в результате чего родилась эта статья, были обнаружены ряд аппаратных ограничений сего девайса (FON 2201), не позволяющих «в полную меру развернуться» и превратить фонеру в гибкое и универсальное устройство, хотя изначальные предпосылки к этому есть (это ведь, попросту, линуксовая машинка). Основной «загвоздкой» явилось весьма малое количество встроенной флэш-памяти (8МБайт), часть которой занимает сама операционка (операционная система, далее «ось»). Устранение данного нюанса путем расширения встроенной памяти (перепайки микросхемы на более емкую) — во-первых трудоемко, во-вторых не решает проблемы координально (максимальное увеличение в 2-4 раза, что, собственно, не много). Вариант распаивать интерфейс SPI для использования карты памяти MMC|SD — мне также не показался привлекательным — скорость этого интерфейса невелика. Да и в целом на текущий момент мне не очень хочется лезть во внутрь моей единственной фонеры (а заполучить еще одну у нас не так-то и просто). Из всего этого стало понятно, что нужен подобный девайс, но с USB-портом … Такой железкой могла бы успешно стать фонера 2.0g (FON 2202) — таже полуторная фонера (как у меня) плюс наличие USB 2.0 порта и удвоенное количество ОЗУ (32МБайта), но добыть ее в России непросто (не переплачивая двойной цены). И в данной ситуации я решил подобрать иной девайс, с целью «прошивки» под OpenWRT и с тем железом, которое нужно мне. А уж раз постановка задачи дала мне возможность выбора, а также было ясно, что по габаритам и функционалу устройств сопоставимых Fonera 2.0g нет, — то планка аппаратных требований была поднята — уже требовалось «переплюнуть» так продвигаемую в сообществе FON фонеру 2.0n (FON 2303). Соответственно требования были таковы:

Выбор пал на DIR825 (HW: B1 или B2) — подробнее о нем в сравнении с разными фонерами можно прочесть в предыдущей статье. К сожалению не так просто выбрать маршрутизатор по его «начинке» — производители скрывают эту информацию, считая ее видимо не интересной для конечного пользователя — а зря …

Теперь к теме настоящей статьи. Материал будет справедлив не только для DIR825, но и для прочих устройств с операционкой OpenWRT BackFire 10.03. Тут несколько определимся в терминах. Понятие «прошивка» для беспроводных маршрутизаторов не отражает объективной картины ее внутреннего функционала. Мы привыкли «прошивать» разные устройства от системных плат и видео-карт до мобильных и стационарных телефонов, плееров и т.п. Во всех этих случаях «прошивка» представляет собой «черный» ящик с неким содержимом, которое по нашему разумению, чем свежее — тем лучше. В случае же с маршрутизаторами работающими под OpenWRT «прошивка» представляет собой сборку базового образа операционной системы, с которой в дальнейшем предстоит работать (дополнять, настраивать и пр.).

OpenWRT в настоящей редакции (для DIR825) представлен в виде двух образов, имеющих координальные различия в своей структуре:

Есть не мало документов на различных сайтах и обсуждений на форумах каким образом «мигрировать» работу оси на внешний USB-флэш накопитель, присутствуют примеры скриптов, в том числе и на официальном сайте OpenWRT. Но есть ряд нюансов, которые недостаточно документированы или не документированы вовсе. В большинстве случаев приводятся лишь куски скриптов, а общую картину приходится достраивать самому.

И так. С первого взгляды бы казалось с первой конфигурацией разделов (все на jffs2) мигрировать должно было бы проще, но при тестировании возникли осложнения с синхронизацией папок /var и /tmp — а на структуре с mini_fo все прошло более гладко (с удалением одной строчки относительно предыдущего варианта). Теперь по пунктам что нужно предпринять:

 

Перенос системы на внешний USB-флэш накопитель.

 

  1. Для начала определимся — в какую файловую систему будем форматировать флэш-накопитель (или жесткий диск). Это может быть ext2 или ext3. Предлагаю остановиться на ext2, ибо основное преимущество ext3 — журналируемость для флэш-накопителей не очевидно (требует больше операций чтение/запись, что не прибавляет шансов на сохранность данных при сравнительно невысоких скоростях). В любом случае рекомендую отключать кеш на запись (в случае с ext3 это сделать чуть сложнее — и в этом случае теряется возможная прелесть журналируемости). Размечать и форматировать накопитель можно как средствами OpenWRT, так и на компе например утилитой parted magic. Тут же можно создать swap-раздел («файл подкачки»). Как основной раздел, так и swap-раздел целесообразно организовывать в виде «основных» разделов (подробности раметки накопителей выходят за рамки данной статьи).
  2. Для начала установим необходимые «драйверы» — модули ядра (с префиксом kmod*) необходимые для взаимодействия с USB-портом, накопителем и файловой системой (можно ограничиться только выбранной файловой системой или сразу добавить и прочие, на будущее — места они занимают мало). Выполнить это можно например следующей командой (предварительно обновив лист репозитория: opkg update — при настроенном подключении маршрутизатора к интернету):
  3. [raw]

    opkg install kmod-usb2 kmod-usb-storage kmod-fs-ext2 kmod-fs-ext3 usbutils e2fsprogs

    [/raw]

    Данные пакеты как и все модули ядра устанавливаются на встроенную память маршрутизатора, даже после того как мы успешно мигрируем.

  4. Создадим файл /etc/init.d/pivotroot следующего содержания (предполагаем что флэшка видна системе как устройство /dev/sda1):
  5. Листинг файла - /etc/init.d/pivotroot
    [raw]

    #!/bin/sh
    # change this to your boot device (put here the name of your umsd drive)
    boot_dev=»/dev/sda1″
    # starting hotplug daemon
    /sbin/hotplug2 —override —persistent —max-children 1 —no-coldplug &
    # loading kernel modules for umsd drive by ext2 & ext3 file system
    for module in nls_base usbcore ehci-hcd scsi_mod sd_mod usb-storage jbd ext2 ext3 ; do {
         insmod $module
         }; done

         # this may need to be higher if your disk is slow to initialize
         sleep 3s
         # check partition for errors & fix it
         e2fsck -p «$boot_dev» > /var/log/e2fsck
         sleep 1s
         # mount the usb stick
         mount -t ext2 «$boot_dev» /mnt
         # mount -t ext3 -o noatime,data=ordered «$boot_dev» /mnt

    killall hotplug2

         # if /etc/pivotroot not empty …
         # and if everything looks ok, do the pivot root
         [ -s /etc/pivotroot ] && [ -x /mnt/sbin/init ] && {
              mount -o move /proc /mnt/proc && \
              pivot_root /mnt /mnt/mnt && {
              mount -o move /mnt/dev /dev
              mount -o move /mnt/tmp /tmp
              mount -o move /mnt/sys /sys 2>&-
              }
         }

    [/raw]

    Присвоим ему права 755. Данный скрипт выполняется в самом начале загрузки оси: выполняет проверку файловой системы на внешнем накопителе на наличие логических ошибок и исправляет их, далее осуществляется монтирование внешнего накопителя и перенаправление «корня» на него(стредствами встроенного в операционную систему скрипта pivot_root).

  6. Пропишем этот скрипт в автозапуск следующей командой:
  7. [raw]

    ln -s /etc/init.d/pivotroot /etc/rc.d/S10pivotroot

    [/raw]

  8. Скопируем файлы операционной системы на внешний накопитель — откуда они впоследствии и будут использоваться (предполагаем что флэшку уже отформатировали, драйвера установили, маршрутизатор перезагрузили). Создадим в каталоге /tmp произвольный файл, присвоим ему права на исполнение (777) и запише в него следующее (для развертывания содержимого — кликните на стрелочку справа от заголовка):
  9. Листинг файла - /tmp/install.sh
    [raw]

    #!/bin/sh
    mkdir /tmp/root
    mount -o bind /rom /tmp/root
    mount /dev/sda1 /mnt
    cp /tmp/root/* /mnt -a
    cp /overlay/* /mnt -a
    umount /tmp/root
    umount /mnt

    [/raw]

    Выполним получившийся скрипт. Эти же строки (за исключением первой) можно выполнить и покомандно.

  10. Модифицируем скрипт /etc/init.d/rcS к следующему виду:
  11. Листинг файла - /etc/init.d/rcS
    [raw]

    #!/bin/sh
    # Copyright (C) 2006 OpenWrt.org

    run_scripts() {
    for i in /etc/rc.d/$1*; do
    [ -x $i ] && $i $2 2>&1
    done | $LOGGER
    }

    LOGGER=»cat»
    [ -x /usr/bin/logger ] && LOGGER=»logger -s -p 6 -t sysinit»

    if test $2 == «boot» ; then
    /etc/init.d/pivotroot
    fi

    if [ «$1″ = «S» ]; then
    run_scripts «$1″ «$2″ &
    else
    run_scripts «$1″ «$2″
    fi

    [/raw]

    Красным помечены добавленные строки.

  12. Создадим файл /etc/pivotroot — поместим в него произвольный текст (хоть один символ — и уже файл не пустой).
  13. Перезагружаемся.
  14. Проверяем что у нас получилось:
  15. [raw]

    df -h

    [/raw]

    отображается структуру разделов оси (последняя строчка указывает, что корень системы теперь на нашем флэш-накопителе).

  16. Для корректности работы выполним еще пару крманд:
  17. [raw]

    rm /etc/resolv.conf
    ln -s /tmp/resolv.conf.auto /etc/resolv.conf

    [/raw]

  18. В случае, если в п.1 был также создан swap-раздел, то организуем его использование. Для этого создадим демона управления в виде файла /etc/init.d/swapctrl:
  19. Листинг файла - /etc/init.d/swapctrl
    [raw]

    #!/bin/sh /etc/rc.common

    START=40
    STOP=40

    start() {
    # Don’t stop processing
    ( startup ) &
    }

    stop() {
    sync
    sync
    swapoff /dev/sda2
    }

    restart() {
    stop
    start
    }

    startup() {
    mkswap /dev/sda2
    swapon /dev/sda2
    }

    [/raw]

    Установим файлу права 755. В данном случае подразумевается что swap-раздел виден системе как /dev/sda2. Активировать swap-раздел (как и любой другой демон) можно командой:

    [raw]

    /etc/init.d/swapctrl start

    [/raw]

    Для автозапуска данного демона можно выполнить:

    [raw]

    /etc/init.d/swapctrl enable

    [/raw]

    Удедиться в активности swap-раздела, а также посмотреть общий раздер доступной памяти можно командой free.

  20. Вот собственно и все. «Старый корень» (содержимое squashfs), при текущем корне на внешнем накопителе — имеет точку монтирования /mnt, как и прежде маскируется через mini_fo из папки /mnt/overlay (учитывая это можно вносить изменения в файлы на встроенной памяти). В случае если нам будет необходимо загрузиться со встроенной памяти (например для установки модулей ядра), то следует очистить содержимое файла /mnt/etc/pivotroot и перезагрузиться — корнем будет структура mini_fo (overlay поверх squashfs) на встроенной памяти. Сотворив необходимые операции — для возврата обратно (к использованию внешнего накопителя в качестве корня) вносим любое содержимое в файл /etc/pivotroot (на встроенной памяти). Файл /etc/pivotroot на внешнем накопителе должен быть пустым!
  21. Есть замечания и вопросы ? — пишем комментарии …

 

Продолжение (2010-09).

Не так давно (июль 2010) в OpenWrt появился новый модуль — «extroot», организующий функцию миграции корня на внешний накопитель меньшими «плясками», в сравнении с описанным выше способом (которому до этого времени альтернативы собственно и не было).

 

Extroot — как им воспользоваться?

 

Для начала можно прочитать доку с официального сайта http://wiki.openwrt.org/doc/howto/rootfsonexternalstorage. Далее обратиться к уже упомянутому мной сайту, и на этот раз статье http://dipcore.com/?p=296. Из прочитанного стоит понять, что без пересборки прошивки в данном случае не обойтись. Обзор и линки на материалы по самостоятельной компиляции прошивки из исходников описаны ранее здесь. Разобраться и собрать прошивку самому — это правильный путь, и в этом нет ничего сложного (и это под силу тем, кто выполнил первую часть этой статьи ;-) Тем немее, кто не хочет заморачиваться с данным процессом, могут воспользоваться последней версией моей компиляции, всегда доступной для скачивания: http://maslenizza.ru/ar71xx/openwrt-ar71xx-dir-825-b1-squashfs-backup-loader.bin.

 

Немножко подробностей.

 

Все статьи на разных сайтах грешат отсутствием четкого алгоритма, более того информация, порой, содержит неточности — в общем всегда приходится не тупо копи-пастить, а включать мозги и обобщать ;-) Так вот еще один элемент для обобщения создаю и я ;-)) Ориентир, как всегда, больше на понимание, чем на тупой алгоритм для «чайника».

  1. Создаем разделы и форматируем наш «внешний накопитель» (жесткий диск, флешку, карту памяти в ридере) любыми средствами (утилитами в маршрутизаторе, опреционкой на виртуальной машине, загрузившись с лайв-сиди) — кому как удобнее. Число разделов и их порядок — опять-таки на ваше усмотрение (лучше создавать все разделы как «основные», а нелогические диски в расширенном). В принципе можно ограничиться и одним разделом — в который и мигрирует наш «корень» — и файловую систему на нем ext2 (не стоит создавать под корень раздел с ext3, тем более на накопителе флеш — из-за пресловутого «журналирования», которое для корректности придется отключать*). Также целесообразно создать swap-раздел. Ну и для упорядочения хранимых данных (в случае большой емкости внешнего накопителя) можно изначально не распределять все пространство между «корнем» и «свопом», а оставить еще местечка под раздел данных, который можно отформатировать в любую linux-систему (ext2, ext3).
  2. Заливаем прошивку (предложенную выше, или собранную самостоятельно). При самостоятельной сборке в образ помимо драйверов usb, внешних накопителей и файловых систем (описано вначале статьи), необходимо также включить модули block-hotplug и block-mount (автоматизация монтирования), e2fsprogs (проверка целостности файловой системы), block-extroot (ради чего все и затевалось).
  3. Убедиться в работоспособности ;-) Скопировать содержимое корня образа на радел внешнего накопителя (в примере подразумевается, что файловая система накопителя ext2, а подключен он как sda1), сформировать swap-раздел (находится на sda2) — при помощи следующего скрипта (или покомандно из консоли):
  4. Листинг файла - /tmp/install.sh
    [raw]


    #!/bin/sh

    mount -t ext2 /dev/sda1 /mnt
    mkdir /tmp/root
    mount -o bind /rom /tmp/root
    cp /tmp/root/* /mnt -a
    mkswap /dev/sda2

    [/raw]

     

  5. И напоследок (перед перезагрузкой) для обеспечения автоматического старта всей конструкции откорректируем файл /etc/config/fstab — приведя его к следующему виду:
  6. Листинг файла - /etc/config/fstab
    [raw]


    config global automount
         option from_fstab 1
         option anon_mount 1

    config global autoswap
         option from_fstab 1
         option anon_swap 0

    config mount
         option target /
         option device /dev/sda1
         option fstype ext2
         option options rw,sync
         option enabled 1
         option enabled_fsck 1
         option is_rootfs 1

    config mount
         option target /root
         option device /dev/sda3
         option fstype ext3
         option options rw,sync
         option enabled 1
         option enabled_fsck 1

    config swap
         option device /dev/sda2
         option enabled 1

    [/raw]

     

    В нашем случае sda1 — новый корень (ext2); sda2 — swap-раздел; sda3 — пользовательская область, монтируемая в /root (ext3). Впрочем значение всех параметров легко угадывается по названию. Считаю не лишним до перезагрузки скопировать этот файл и на новый корень, после чего выполнить команду sync и umount /mnt.

     

  7. Все (правда — все значительно упростилось?).

 

«Лирические отступления» — по тексту .

 

* «Журналирование» — хитрый процесс, в теории направленный на повышение вероятности сохранения целостности данных на накопители при внезапном его отключении в самые неподходящие моменты. Под «журнал» выделяется (резервируется) часть дискового пространства (пропорциональная его емкости). Журналироваться могут как непосредственно сами данные, так и только метаинформация. В первом случае запись происходит не на предполагаемое место хранения данных на диске в отведенную область журнала (при отключении диска на этой стадии и последующем включении и проверке — данные журнала признаются недействительными, а фактическая информация на диске остается в целостности, хоть и в устаревшем виде) — в случае успеха делается пометка, что для фактических данных требуется обновление из журнала. Далее предполагается процесс обновления фактических данных по данным «журнала» (при отключении накопителя в этот момент — считаются подлинными данные журнала, попытка записи которых на фактическое место происходит повторно) — в случае успеха (проверки соответствия) делаются соответствующие пометки и журнал «очищается». Такой алгоритм в два раза снижает скорость записи на накопитель, а в случае использования флеш-накопителя существенно способствует его износу (журнал хранится в фиксированном месте и являясь буфером постоянно перезаписывается). Если же применяется алгоритм журналирования метаинформации — достичь безусловной целостности не удастся — возможно лишь зафиксировать ее нарушения (метаинформация — фактически контрольные суммы блоков данных на накопителе). Как показала практика использование системы ext3 под «корнем» на внешнем накопителе с журналированием только метаинформации (режим по умолчанию) ведет к частому нарушению целостности информации (возможно мнимому), на инфа «коцаеца» корректность работы теряется, приходится либо включать полное журналирование (что для флеш-накопителя нежелательно по описанным выше причинам), либо отключать его вовсе — тогда вопрос: зачем на ext3 без журналирования — это уже фактически ext2 (использовать которую под «корень» я и рекомендую).

Comments

This post currently has 31 responses

  • Поменяй диски местами в разъемах хаба…
    Порты USB-хаба имеют аппаратную нумерацию, зачастую не соответствующую последовательности их распайки (например у меня так: 1-4-2-3) … определить эту последовательность имхо проще какой-нибудь информационной утилитой под винду.
    Линукс же сканирует устройства по портам хаба в соответствие с их нумерацией и присваивает им символические имена (например sda, sdb и т.п.). Системный накопитель целесообразно подключать к первому (по аппаратной нумерации) порту хаба. Иначе если очередной диск окажется подключенным (а следовательно при загрузке инициализированным) ранее системного диска — то системный диск будет иметь уже другое имя …

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *


*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>