Це БУГ!
Це помилка, яка виникає в останній версії Ubuntu Server LTS (Ubuntu Server 14.04 LTS), коли ви створюєте завантажувальний розділ (або кореневий розділ, коли завантажувальний розділ не існує) всередині LVM або розділу RAID .
Ви можете отримати більш детальну інформацію про цю помилку в стартовій панелі Ubuntu: Помилка № 1274320 "Помилка: записи diskfilter не підтримуються" .
Оновлення: ця помилка вже виправлена в 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).
Функція GRF Recordfail використовує save_env
оператор для оновлення стану рекорду (див. Довідка Ubuntu - Grub 2 , розділ "Остання помилка завантаження або завантаження в режим відновлення"). Однак в Ubuntu 14.04 (і в останніх версіях Debian) save_env
оператор (всередині функції rekfail) використовується, навіть якщо 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
заяву про запис і напишіть відповідний коментар у /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