корневая файловая система btrfs на raspbian

11

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

Что я сделал:

  1. на ПИ до переключения:

    apt-get install btrfs-tools 2. С компьютера с Linux:

    btrfs-convert / dev / sda2

  2. В /etc/fstabзамен ext4наbtrfs

  3. В /cmdline.txtзамен ext4наbtrfs

Я получаю панику ядра, если я пытаюсь сделать загрузку. Должен ли я сделать что-нибудь еще?

GuySoft
источник

Ответы:

7

Если btrfs скомпилирован как модуль ядра, вам нужно создать initramfs для загрузки модуля при загрузке. На Raspian (и других производных Debian) update-initramfsэто самый простой способ сделать это.

Если initramfs-toolsустановлено, то каждый раз, когда apt-getустанавливается новое ядро, оно должно запускаться update-initramfsавтоматически.

sudo apt-get update
sudo apt-get install initramfs-tools

Однако, если вы используете rpi-updateдля установки нового ядра, вам нужно будет запустить его update-initramfsвручную перед перезагрузкой в ​​новом ядре:

sudo update-initramfs -u -k <kernel-version>

Это создаст или обновит initramfs в /boot/initrd.img-<kernel-version>.

Последний шаг - добавить его в конфигурацию загрузки: добавьте следующую строку в /boot/config.txt:

initramfs initrd.img-<kernel-version> followkernel

initrd-<kernel-version>должно точно соответствовать имени файла в /boot.

Вам нужно будет повторять эти шаги при каждом запуске rpi-update.

bennettp123
источник
2

Мой быстрый тест показывает, что поддержка btrfs встроена в raspbian как внешний модуль, не связанный напрямую с ядром.

Это означает, что ядро ​​должно иметь возможность загрузить этот модуль (который хранится в корневой файловой системе), прежде чем он сможет смонтировать корневую файловую систему. Очевидно, это не работает.

Подход 1:

Создайте свое собственное ядро ​​и настройте его конфигурацию, чтобы предварительно связать btrfs. Настроить конфигурацию легко, если вы выяснили, как собрать и загрузить собственное ядро.

Подход 2:

Выполните перенастройку, чтобы ядро ​​и модули находились в файловой системе ext4, а данные, которые вы хотите сжать, - в разделе btrfs.

Подход 2А:

Оставьте корневой раздел как ext4 и создайте новый раздел на основе btrfs, но это не поможет сократить установку ОС (если это ваша цель).

Подход 2В:

Создайте маленький загрузочный раздел, содержащий ядро ​​и модули, оставив все остальное на btrfs. Я понятия не имею, как сделать это для загрузчика Пи, или каковы ограничения вокруг этого.

Донгар
источник
Как насчет копирования модулей btrfs в загрузочный раздел и загрузки их оттуда заранее?
GuySoft
3
Разве нельзя также начать с initrd.img?
Андерс
Да, и initrd.img выглядит как самый простой способ решить эту проблему! Я просто никогда не использовал это. Ищите документы на "mkinitrd".
ДонГар
Хмм, похоже, что CONFIG_BLK_DEV_INITRD не включен в последней версии Raspbian. Это означает, что вам нужно перекомпилировать ядро, чтобы включить поддержку initd.
GuySoft
1
См. Paxswill.com/blog/2013/11/04/encrypted-raspberry-pi - там initramfs используется для разрешения зашифрованного корня. Точно так же поддержка cryptsetup (здесь btrfs) необходима прежде, чем станет доступен root.
Rbjz
1

Чтобы он нашел мой внешний корневой раздел BTRFS, мне нужно было явно указать UUID корневого раздела в загрузочном разделе cmdline.txt. Например:

dwc_otg.lpm_enable = 0 console = tty1 root = PARTUUID = 123e4567-e89b-12d3-a456-426655440000 rootfstype = btrfs elevator = крайний срок rootwait тихий всплеск

Вы можете определить UUID раздела BTRFS, используя lsblk -f.

Geremia
источник
1

Ядро Raspbian не включает поддержку btrfsпо умолчанию; начальные этапы загрузки проходят нормально, но когда ядро ​​загружается, оно не видит файловую систему, которую оно может смонтировать - и паникует. Решение существует: добавьте btrfs в качестве модуля ядра в initramfs. Во многом благодаря трем различным статьям я настроил это так:

  • Установите необходимые пакеты - модуль ядра и инструменты для обновления initramfs: sudo apt install btrfs-tools initramfs-tools
  • Скажите initramfs, чтобы загрузить модуль btrfs (должен происходить автоматически, по какой-то причине не работал на моем RPi1) - добавьте строку с "btrfs" в список необходимых модулей: echo 'btrfs' | sudo tee -a /etc/initramfs-tools/modules
  • Создайте ловушку initramfs (для создания образа) и сценарий (для загрузки) для btrfs - значения по умолчанию предоставлены, но в моем тестировании они не использовались автоматически, их пришлось скопировать в / etc. sudo mkdir -p /etc/initramfs-tools/hooks ; sudo mkdir -p /etc/initramfs-tools/scripts/local-premount ; sudo cp /usr/share/initramfs-tools/hooks/btrfs /etc/initramfs-tools/hooks ; sudo cp /usr/share/initramfs-tools/scripts/local-premount/btrfs /etc/initramfs-tools/scripts/local-premount; sudo chmod +x /etc/initramfs-tools/hooks/btrfs /etc/initramfs-tools/scripts/local-premount/btrfs
  • Создать ( -c) новые initramfs для текущей версии ядра (uname -r) - если вы обновляете существующую, вам нужно будет использовать update ( -u). Это создаст файл с именем вроде /boot/initrd.img-*, где * - текущая версия ядра. Обратите внимание на сгенерированное имя (скрипт выведет его), мы будем использовать его на следующем шаге.update-initramfs -c -k $(uname -r)
  • Отредактируйте, /boot/config.txtчтобы использовать этот initramfs, добавив initramfs initrd.img-3.11.0+ followkernelИмя файла без пути, это имя, созданное на предыдущем шаге; «followkernel» контролирует расположение в памяти ( документация config.txt ).
  • Это решает текущее ядро, но, как указал @Ingo, обновление ядра сломало бы систему. Чтобы исправить это, я использовал его скрипты -обработчики ядра :

    • Отредактируйте / etc / default / raspberrypi-kernel и раскомментируйте INITRD=Yes
    • удалять /etc/kernel/postinst.d/initramfs-tools
    • добавьте rpi-initramfs-tools в /etc/kernel/postinst.d/ и chmod +xэто
    • при необходимости загрузите update-rpi-initramfs для более простых обновлений initramfs вручную.
  • На данный момент у нас есть система, которая может использовать btrfs в качестве корневого устройства. Тестирование путем перезагрузки: система по-прежнему будет загружаться из раздела ext4 (или из того, что находится в вашем /boot/cmdline.txt ), но dmesg | grep -i btrfsтеперь должна показать строку, содержащую «Btrfs загружен». Теперь нам нужно создать и использовать раздел btrfs.

  • Сделайте резервную копию /раздела (ext4) - предположим, что это / dev / mmcblk0p2 - обычно: выключите RPi, выньте SD-карту, подключите ее где-нибудь еще (в этом примере sudo mount /dev/mmcblk0p2 /mntна компьютере с Linux) и заархивируйте содержимое; обратите внимание, что вам нужно использовать инструмент, который сохраняет права собственности и права доступа, например tar: cd /mnt; sudo tar -czvf ~/rpi-rootfs-backup.tgz *(а затем снова отключить SD-карту)

  • Создайте раздел btrfs где-нибудь - я повторно использовал SD-карту, заменив раздел ext4 (/ dev / mmcblk0p2); если вы хотите создать массив btrfs-raid, самое время это сделать ( это один из аргументов mkfs.btrfs , выходящий за рамки этого ответа):mkfs.btrfs /dev/mmcblk0p2
  • Смонтируйте раздел btrfs и восстановите в нем резервную копию: sudo partprobe; sudo mount /dev/mmcblk0p2 /mnt; cd /mnt; tar -xzvf ~/rpi-rootfs-backup.tgz
  • Отредактируйте fstab в разделе btrfs :sudo nano /mnt/etc/fstab

Должна быть строка, похожая на эту:

/dev/mmcblk0p2  / ext4 foo,bar,baz 0 1

Измените это на это (новый тип FS - btrfs, и он использует параметры по умолчанию):

/dev/mmcblk0p2  / btrfs defaults 0 1
  • Размонтируйте раздел, но пока не извлекайте SD-карту! sudo umount /mnt
  • Нам нужно сообщить RPi, что он будет загружаться с btrfs
  • Найдите UUID вашего нового раздела btrfs - найдите строку с / dev / mmcblk0p2 и скопируйте часть UUID = с помощью (не UUID_SUB, не PARTUUID! Это приведет к ошибке в загрузчике, и ядро ​​не загрузится .):sudo blkid

    / dev / mmcblk0p2: UUID = "cafebeef-0000-1234-aaaa-12346589" UUID_SUB = "ababccdd-2345-cafe-beee-587989991110" TYPE = "btrfs" PARTUUID = "beef0bee-02"

  • Смонтируйте загрузочный (FAT32) раздел: sudo mount /dev/mmcblk0p1 /mnt

  • Изменить cmdline.txt: sudo nano /mnt/cmdline.txt

Найдите эти два параметра

 root=PARTUUID=1234-5678 rootfstype=ext4

И заменить на

 root=UUID=cafebeef-0000-1234-aaaa-12346589 rootfstype=btrfs

Обратите внимание, что UUID - это тот, который мы скопировали ранее, без кавычек.

  • Размонтируйте загрузочный раздел RPi: sudo umount /mnt
  • Замените SD-карту в RPi и загрузитесь.
  • На RPi убедитесь, что вы действительно работаете с корневого монтирования btrfs: mount

    / dev / mmcblk0p2 on / type btrfs (rw, space_cache, subvol = /)

  • И вуаля! Не совсем по принципу «укажи и щелкни», но, стоя на плечах гигантов, я мог заставить это работать. (Сделал это в репо тоже.)

Писквор покинул здание
источник
1
Во-первых, sudo apt upgradeесли он также обновит ядро, эта установка будет неудачной при загрузке, потому что новое ядро ​​пытается загрузить старые initramfs, которые потерпят неудачу, и ядро ​​не может загрузить драйверы btrfs. И это не простой способ исправить это, по крайней мере, с помощью chrootсистемы armhf.
Инго
Разве update-initramfs не будет вызываться при обновлении ядра?
Писквор покинул здание
1
Нет, Raspbian по умолчанию не может генерировать новые initramfs. Это не настроено для этого. apt upgradeПеред тем, как загружать новое ядро, вы всегда должны следить за своими действиями и генерировать initramfs вручную, если это необходимо. Не выполнимое задание для новичка, потому что провалить это драматично. Вы можете посмотреть, как я могу использовать ramdisk init (initramfs) при загрузке Raspberry Pi?
Инго
1
В ней есть небольшая ошибка, которую я только что обнаружил, но до сих пор не исправил. Ядро поддерживает две модели, например 4.14.98+и 4.14.98-v7+. Если update-initramfs запускается обновлением ядра, он сгенерирует два initrd.img *, по одному для каждой модели. Это не помещается на /bootраздел (ошибка - из-за нехватки места) и генерация не заканчивается.
Инго
1
Я считаю, чтобы использовать MODULES=list.
Инго