Ini BUG!
Ini adalah bug yang muncul di versi terbaru dari Ubuntu Server LTS (Ubuntu Server 14.04 LTS), ketika Anda membuat partisi boot (atau partisi root, ketika partisi boot tidak ada) di dalam LVM atau partisi RAID .
Anda bisa mendapatkan info lebih lanjut tentang bug ini di Ubuntu Launchpad: Bug # 1274320 "Kesalahan: penulisan diskfilter tidak didukung" .
Pembaruan: Bug ini sudah diperbaiki di Ubuntu Server 14.04 dan beberapa versi Ubuntu yang lebih baru. Mungkin, Anda hanya perlu berlari apt-get upgrade
.
Mengapa bug ini terjadi?
Ketika sistem boot, GRUB membaca ( load_env
) data di /boot/grub/grubenv
. File ini disebut Blok Lingkungan GRUB .
Dari Manual GRUB:
Seringkali berguna untuk mengingat sejumlah kecil informasi dari satu boot ke boot berikutnya.
[...]
Pada saat boot, perintah load_env (lihat load_env) memuat variabel lingkungan darinya, dan perintah save_env (lihat save_env) menyimpan variabel lingkungan ke dalamnya.
[...]
grub-mkconfig
menggunakan fasilitas ini untuk mengimplementasikan GRUB_SAVEDEFAULT
Perilaku ini dapat ditemukan di /etc/grub.d/00_header
( update-grub
menggunakan file ini untuk menghasilkan /boot/grub/grub.cfg
file):
if [ -s $prefix/grubenv ]; then
set have_grubenv=true
load_env
fi
Masalahnya adalah save_env
pernyataan itu hanya berfungsi pada instalasi sederhana (Anda tidak bisa menjalankan save_env
disk RAID atau LVM). Dari manual GRUB:
Untuk alasan keamanan, penyimpanan ini hanya tersedia ketika diinstal pada disk biasa (tanpa LVM atau RAID), menggunakan sistem file non-checksumming (tanpa ZFS), dan menggunakan fungsi BIOS atau EFI (tanpa ATA, USB atau IEEE1275).
Fitur GRUB recordfail menggunakan save_env
pernyataan untuk memperbarui status recordfail (lihat Bantuan Ubuntu - Grub 2 , bagian "Boot Terakhir Gagal atau Boot ke Mode Pemulihan"). Namun, dalam Ubuntu 14.04 (dan dalam versi Debian terbaru), save_env
pernyataan (di dalam fitur recordfail) digunakan bahkan jika GRUB diinstal dalam LVM atau RAID.
Mari kita lihat garis dari 104 hingga 124 di /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 melewatkan fitur recordfail dengan benar ketika menggunakan sistem file yang tidak didukung (btrfs, zfs, dll), tetapi tidak melewatkan LVM dan RAID setiap saat .
Bagaimana GRUB melindungi dirinya dari penulisan di dalam RAID dan LVM?
Untuk membaca / menulis dengan benar di sistem file, GRUB memuat modul yang sesuai.
GRUB menggunakan modul diskfilter ( insmod diskfilter
) di partisi RAID, dan modul lvm di partisi LVM.
Mari kita lihat implementasi baca / tulis dari modul diskfilter :
apt-get source grub2
vim grub2-2.02~beta2/grub-core/disk/diskfilter.c
Saya menempelkan kode di sini (baris dari 808 ke 823). Peringatan yang ditunjukkan dalam pertanyaan ini muncul di baris 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");
}
The grub_diskfilter_read
fungsi diimplementasikan (dan GRUB dapat membaca filesystem RAID). Namun, grub_diskfilter_write
fungsi ini menimbulkan GRUB_ERR_NOT_IMPLEMENTED_YET
kesalahan.
Mengapa menggunakan quick_boot=0
memecahkan masalah? Dan mengapa itu solusi yang salah?
Jika Anda melihat sekali lagi dalam /etc/grub.d/00_header
kode, Anda akan melihat bahwa fitur recordfail hanya digunakan saat quick_boot=1
. Jadi, mengubah quick_boot
dari 1 ke 0 menonaktifkan fitur recordfail, dan menonaktifkan menulis di partisi RAID / LVM.
Namun, itu juga akan menonaktifkan banyak fitur lainnya (jalankan grep \$quick_boot /etc/grub.d/*
dan Anda akan melihat). Terlebih lagi, jika suatu hari Anda mengubah /boot/grub
direktori Anda ke luar RAID / LVM, fitur recordfail masih akan dinonaktifkan.
Singkatnya, solusi ini tidak perlu menonaktifkan fitur, dan itu tidak umum.
Apa solusi yang benar?
Solusi yang benar harus mempertimbangkan menonaktifkan save_env
pernyataan ketika GRUB berada di dalam partisi LVM atau RAID.
Satu tambalan diusulkan dalam sistem Debian Bug Tracker untuk mengimplementasikan solusi ini. Itu dapat ditemukan di: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=754921
Gagasan di balik tambalan ini adalah:
- Jalankan
grub-probe --target=abstraction "${grubdir}"
perintah untuk mendapatkan modul abstraksi seperti apa yang digunakan GRUB untuk membaca / menulis file di /boot/grub
direktori;
- Jika GRUB menggunakan modul
diskfilter
atau lvm
, lewati save_env
pernyataan recordfail dan tulis komentar yang sesuai dalam /boot/grub/grub.cfg
file;
- Sebagai contoh,
# GRUB lacks write support for /dev/md0, so recordfail support is disabled.
Bagaimana cara menerapkan solusi yang benar?
Jika Anda tidak ingin menunggu tambalan ini diterapkan oleh orang-orang Ubuntu / Debian dalam kode resmi, Anda dapat menggunakan tambalan saya 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