[ KOI8 | CP1251(MS-Windows) | CP866(DOS) | ISO8859-5 | Mac ]


Пожалуйста, прочтите Правила копирования и использования данных материалов.

Обеспечение целостности файловой системы при внезапных выключениях роутера

Проблема

Внезапные выключения PC-роутера (как и любой Linux-машины) могут привести к нарушениям корректности файловой системы. Повреждения возникают из-за того, что операции с файловой системой не являются неделимыми; например, модификация файла включает в себя изменение как блоков файла, так и описателя файла (i-node), списка свободных блоков и т.д., которые записываются на диск несколькими раздельными операциями записи. После выполнения первой из операций и вплоть до завершения последней файловая система на диске находится в промежуточном, переходном состоянии; если в этот момент произойдет выключение, файловая система так и останется в некорректном состоянии и будет требовать починки (fsck).

Во многих случаях повреждения оказываются несерьезными, так что при загрузке системы возможна автоматическая починка без потери файлов (fsck -a). Тем не менее, существует вероятность серьезного повреждения, которое потребует починки в ручном режиме и, возможно, восстановления потерянных файлов. Поэтому допускать повреждения файловой системы нельзя, ибо это противоречит принципу необслуживаемости (см. раздел 2.2) изделия.

Решение

Поскольку повреждения возникают исключительно как результат незавершенных операций записи на диск, мы можем избежать повреждений, работая с диском в режиме "только на чтение" (read-only, r/o). Однако просто смонтировать весь диск read-only нельзя, поскольку для полноценной работы системы требуется, чтобы некоторые каталоги (/tmp, /var/run, /var/log, ...) работали в режиме "чтение и запись" (read/write, r/w). При этом записываемая в эти каталоги информация носит преходящий характер (временные файлы, .pid файлы, файлы с отладочными протоколами и т.д.). Поэтому полноценное решение выглядит так:

  1. Диск разбиваем на два раздела, один read-only, другой read/write, и файловое дерево распределяем между разделами так, чтобы требующие модификации каталоги находились на втором из них;
  2. Поскольку r/w раздел при выключении машины повреждается, при загрузке системы мы создаем его (mkfs) заново и инициализируем с мастер-копии, хранящейся на корневом разделе.

Реализация

r/w раздел монтируется на /var/lib/roroot/volatile, и при старте системы (/etc/init.d/boot) инициализируется из /var/lib/roroot/volatile.ini. Каталоги на r/o разделе, для которых необходимо обеспечить возможность записи, заменяются на символические ссылки на соответствующие им каталоги на r/w разделе:

ln -s /var/lib/roroot/volatile/X/Y/Z /X/Y/Z

Несколько моментов требуют особого обхождения при переходе к работе с корневым разделом в режиме r/o.

Каталог /etc/mtab

/etc/mtab модифицируется командой mount при монтировании и отмонтировании устройств. "mount -n" опускает модификацию mtab, но тогда некоторые команды, которые берут из mtab информацию о смонтированных файловых системах (например, df и собственно mount) будут работать неидеально.

К счастью, существует файл /proc/mounts, совпадающий по формату с /etc/mtab, и содержащий постоянно верную информацию о смонтированных файловых системах.

Поэтому решение проблемы с /etc/mtab следущее: /etc/mtab заменяем символической ссылкой на /proc/mounts, и всегда используем "mount -n".

Таблица зависимостей модулей
/lib/modules/`uname -r`/modules.dep

Таблица зависимостей модулей существенна для работы modprobe и, следственно, kerneld, короче, для автоматической загрузки модулей ядра. /etc/init.d/modutils строит этот файл заново, если он не существует. Поскольку /lib/modules/`uname -r`/modules.dep находится на r/o разделе, это не будет работать просто так. Мы модифицируем /etc/init.d/modutils, чтобы на время построения modules.dep изменить режим монтирования корневой файловой системы на r/w.

Это не идеальное решение, поскольку машина оказывается на какое-то время уязвима для пропадания питания. Однако это время весьма мало (несколько секунд), и небольшой риск вполне окупается гарантией существования актуального modules.dep.

Файл /bin/login

В процессе входа пользователя в систему, login пытается выполнить смену владельца и режимов доступа (chown, chmod) для /dev/ttyXXX, на котором происходит вход. Поскольку каталог /dev находится на r/o разделе, эти операции заканчиваются неудачей.

Смена владельца и режмов доступа терминала не критична (не создает возможности несанкционированного, либо невозможности санкционированного доступа) для роутеров, где обычно единственным пользователем системы является root. Однако login проверяет код завершения операций chown и chmod, и в случае неудачи обрывает процедуру входа--это означает невозможность входа в систему, если каталог /dev находится на r/o разделе. Разместить же /dev на r/w разделе нельзя, поскольку его присутствие необходимо на этапе раскрутки системы--в частности, для монтирования r/w раздела.

Поэтому для роутеров используется модифицированнaя версия /bin/login, которая спокойно воспринимает завершение chown/chmod с ошибкой EROFS.

Постоянные r/w каталоги

На роутерах иногда все-таки возникает потребность записывать файлы так, чтобы они переживали выключение питания. Например, некоторые файлы статистики, или, скажем, база мигрирующих IP-адресов (pppmlogin.db) на роутере, выполняющем функции терминального сервера. Если первую проблему еще можно пытаться решать при помощи "syslog to remote host", то вторая в рамках описанного деления на r/o - r/w разделы не решается.

Решение дает использование удаленного сервера для хранения файлов. Аналогично монтированию r/w раздела на /var/lib/roroot/volatile, мы монтируем (mount -t nfs) удаленный диск на /var/lib/roroot/remote. Также аналогично, каталоги на r/o разделе, для которых необходимо обеспечить режим "r/w с постоянным хранением", заменяются на символические ссылки на соответствующие им подкаталоги на удаленном диске:

ln -s /var/lib/roroot/remote/X/Y/Z /X/Y/Z

Конфигурация системы для работы в описанном режиме

Я надеюсь в обозримом будущем изготовить автоматически инсталлируемый пакет (roroot-NNN.deb), который при инсталляции (dpkg -i) будет создавать все необходимые каталоги, линки и т.д. А пока придется вручную; можно использовать файловое дерево dish-routerа в качестве прототипа.

Нарезка диска:

dish-router:~# fdisk
Using /dev/hda as default device!

Command (m for help): p

Disk /dev/hda: 10 heads, 34 sectors, 984 cylinders
Units = cylinders of 340 * 512 bytes

   Device Boot   Begin    Start      End   Blocks   Id  System
/dev/hda1            1        1       20     3383    1  DOS 12-bit FAT
/dev/hda2   *       21       21      562    92140   83  Linux native
/dev/hda3          563      563      755    32810   82  Linux swap
/dev/hda4          756      756      984    38930   83  Linux native

Command (m for help):


Несколько ссылок на модифицированные файлы:

Список r/w каталогов:

dish-router:~# ls -l `find / -lname '*roroot*'`
lrwxrwxrwx 1 root root  28 Sep 29 22:41 /tmp -> /var/lib/roroot/volatile/tmp
lrwxrwxrwx 1 root root  36 Sep 30 17:47 /var/backups -> /var/lib/roroot/volatile/var/backups
lrwxrwxrwx 1 root root  35 Sep 29 22:41 /var/catman -> /var/lib/roroot/volatile/var/catman
lrwxrwxrwx 1 root root  33 Sep 29 22:41 /var/lock -> /var/lib/roroot/volatile/var/lock
lrwxrwxrwx 1 root root  32 Sep 29 22:41 /var/log -> /var/lib/roroot/volatile/var/log
lrwxrwxrwx 1 root root  32 Sep 29 22:41 /var/run -> /var/lib/roroot/volatile/var/run
lrwxrwxrwx 1 root root  38 Sep 29 22:41 /var/spool/lpd -> /var/lib/roroot/volatile/var/spool/lpd
lrwxrwxrwx 1 root root  40 Sep 29 22:41 /var/spool/smail -> /var/lib/roroot/volatile/var/spool/smail
lrwxrwxrwx 1 root root  32 Sep 29 22:41 /var/tmp -> /var/lib/roroot/volatile/var/tmp






sizif@botik.ru

Last modified: Sun Oct 5 00:15:27 MSD 1997