Это ошибка!
Эта ошибка возникает в самой последней версии Ubuntu Server LTS (Ubuntu Server 14.04 LTS), когда вы создаете загрузочный раздел (или корневой раздел, если загрузочный раздел не существует) внутри LVM или раздела RAID. ,
Вы можете получить больше информации об этой ошибке в Ubuntu Launchpad: Ошибка # 1274320 «Ошибка: запись в дисковый фильтр не поддерживается» .
Обновление: эта ошибка уже исправлена в Ubuntu Server 14.04 и некоторых более новых версиях Ubuntu. Вероятно, вам нужно только бежать apt-get upgrade
.
Почему эта ошибка возникает?
Когда система загружается, GRUB читает ( load_env
) данные в /boot/grub/grubenv
. Этот файл называется GRUB Environment Block .
Из руководства GRUB:
Часто полезно иметь возможность запомнить небольшое количество информации от одной загрузки к другой.
[...]
Во время загрузки команда load_env (см. Load_env) загружает из нее переменные среды, а команда save_env (см. Save_env) сохраняет в ней переменные среды.
[...]
grub-mkconfig
использует эту возможность для реализации GRUB_SAVEDEFAULT
Это поведение может быть основано /etc/grub.d/00_header
( update-grub
использует этот файл для генерации /boot/grub/grub.cfg
файла):
if [ -s $prefix/grubenv ]; then
set have_grubenv=true
load_env
fi
Проблема в том, что save_env
оператор работает только в простых установках (вы не можете работать save_env
внутри диска RAID или LVM). Из руководства GRUB:
По соображениям безопасности это хранилище доступно только при установке на обычном диске (без LVM или RAID), с использованием файловой системы без контрольной суммы (без ZFS) и с использованием функций BIOS или EFI (без ATA, USB или IEEE1275).
Функция GRUB recordfail использует save_env
оператор для обновления состояния ошибки записи (см. Справку Ubuntu - Grub 2 , раздел «Последняя загрузка не выполнена или загрузка в режим восстановления»). Однако в Ubuntu 14.04 (и в последних версиях Debian) save_env
оператор (внутри функции recordfail) используется, даже если GRUB установлен в LVM или RAID.
Давайте посмотрим строки от 104 до 124 в /etc/grub.d/00_header
:
if [ "$quick_boot" = 1 ]; then
[...]
case "$FS" in
btrfs | cpiofs | newc | odc | romfs | squash4 | tarfs | zfs)
cat <<EOF
# GRUB lacks write support for $FS, so recordfail support is disabled.
[...]
if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
GRUB корректно пропускает функцию ошибки записи при использовании неподдерживаемых файловых систем (btrfs, zfs и т. Д.), Но не пропускает LVM и RAID в любой момент .
Как GRUB защищает себя от записи внутри RAID и LVM?
Для правильного чтения / записи в файловых системах GRUB загружает соответствующий модуль.
GRUB использует модуль diskfilter ( insmod diskfilter
) в разделах RAID и модуль lvm в разделах LVM.
Давайте посмотрим реализацию чтения / записи модуля diskfilter :
apt-get source grub2
vim grub2-2.02~beta2/grub-core/disk/diskfilter.c
Я вставляю код здесь (строки от 808 до 823). Предупреждение, показанное в этом вопросе, появляется в строке 821:
static grub_err_t
grub_diskfilter_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
}
static grub_err_t
grub_diskfilter_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
{
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"diskfilter writes are not supported");
}
grub_diskfilter_read
Функция реализована (и GRUB может читать RAID файловые системы). Однако эта grub_diskfilter_write
функция вызывает GRUB_ERR_NOT_IMPLEMENTED_YET
ошибку.
Почему использование quick_boot=0
решает проблему? И почему это неправильное решение?
Если вы посмотрите еще раз в /etc/grub.d/00_header
коде, вы увидите, что указанная ошибка записи используется только тогда, когда quick_boot=1
. Таким образом, изменение quick_boot
от 1 до 0 отключает функцию сбоя записи и запрещает запись в раздел RAID / LVM.
Тем не менее, он также отключит многие другие функции (запустите, grep \$quick_boot /etc/grub.d/*
и вы увидите). Более того, если однажды вы смените /boot/grub
каталог за пределы RAID / LVM, функция записи по-прежнему будет отключена.
В общем, это решение без необходимости отключает функции, и оно не является универсальным.
Какое правильное решение?
Правильное решение должно учитывать отключение save_env
операторов, когда GRUB находится внутри разделов LVM или RAID.
В системе Debian Bug Tracker был предложен один патч для реализации этого решения. Его можно найти по адресу : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=754921.
Идея этого патча заключается в следующем:
- Запустите
grub-probe --target=abstraction "${grubdir}"
команду, чтобы узнать, какие модули абстракции GRUB использует для чтения / записи файлов в /boot/grub
каталоге;
- Если GRUB использует модуль
diskfilter
или lvm
, пропустите save_env
оператор recordfail и запишите соответствующий комментарий в /boot/grub/grub.cfg
файл;
- Например,
# GRUB lacks write support for /dev/md0, so recordfail support is disabled.
Как правильно применить решение?
Если вы не хотите ждать, пока этот патч будет применен ребятами из Ubuntu / Debian в официальном коде, вы можете использовать мой патч 00_header
:
# Download
wget https://gist.githubusercontent.com/rarylson/da6b77ad6edde25529b2/raw/99f266a10e663e1829efc25eca6eddb9412c6fdc/00_header_patched
# Apply
mv /etc/grub.d/00_header /etc/grub.d/00_header.orig
mv 00_header_patched /etc/grub.d/00_header
# Disable the old script and enable the new one
chmod -x /etc/grub.d/00_header.orig
chmod +x /etc/grub.d/00_header
# Update Grub
update-grub