C'est un bogue!
C’est un bogue qui se produit dans la version la plus récente d’Ubuntu Server LTS (Ubuntu Server 14.04 LTS) lorsque vous créez la partition de démarrage (ou la partition racine, lorsque la partition de démarrage n’existe pas) dans un LVM ou une partition RAID.
Vous pouvez obtenir plus d'informations sur ce bogue dans Ubuntu Launchpad: Bug n ° 1274320 "Erreur: diskfilter les écritures ne sont pas prises en charge ".
Mise à jour : ce bogue est déjà résolu dans Ubuntu Server 14.04 et dans certaines versions plus récentes d’Ubuntu. Vous n’avez probablement besoin que d’exécuter apt-get upgrade
.
Pourquoi ce bogue survient-il?
Lors du démarrage du système, GRUB lit ( load_env
) les données dans /boot/grub/grubenv
. Ce fichier s'appelle bloc d'environnement GRUB .
Extrait du manuel GRUB:
It is often useful to be able to remember a small amount of information from one boot to the next.
[...]
At boot time, the load_env command (see load_env) loads environment variables from it, and the save_env (see save_env) command saves environment variables to it.
[...]
grub-mkconfig
uses this facility to implement GRUB_SAVEDEFAULT
Ce comportement peut être trouvé dans /etc/grub.d/00_header
( update-grub
utilise ce fichier pour générer le fichier /boot/grub/grub.cfg
):
if [ -s $prefix/grubenv ]; then
set have_grubenv=true
load_env
fi
Le problème est que l'instruction save_env
ne fonctionne que dans les installations simples (vous ne pouvez pas exécuter save_env
dans un disque RAID ou LVM). Du manuel GRUB:
For safety reasons, this storage is only available when installed on a plain disk (no LVM or RAID), using a non-checksumming filesystem (no ZFS), and using BIOS or EFI functions (no ATA, USB or IEEE1275).
La fonctionnalité GRUB recordfail utilise l'instruction save_env
pour mettre à jour l'état recordfail (voir Aide Ubuntu - Grub 2 , section "Échec du dernier démarrage ou démarrage en mode de récupération"). Cependant, dans Ubuntu 14.04 (et dans les versions récentes de Debian), l’instruction save_env
(à l’intérieur de la fonctionnalité recordfail) est utilisée même si GRUB est installé dans un LVM ou un RAID.
Voyons les lignes de 104 à 124 dans /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 ignore correctement la fonction recordfail lorsqu’il utilise des systèmes de fichiers non pris en charge (btrfs, zfs, etc.), mais il ne saute pas LVM et le RAID à tout moment .
Comment GRUB se protège-t-il de l'écriture à l'intérieur de RAID et LVM?
Pour lire / écrire correctement dans un système de fichiers, GRUB charge un module approprié.
GRUB utilise le module filtre de disque ( insmod diskfilter
) dans les partitions RAID et le module lvm dans les partitions LVM.
Voyons l'implémentation en lecture / écriture du module diskfilter :
apt-get source grub2
vim grub2-2.02~beta2/grub-core/disk/diskfilter.c
Je colle le code ici (lignes 808 à 823). L’avertissement affiché dans cette question apparaît à la ligne 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");
}
La fonction grub_diskfilter_read
est implémentée (et GRUB peut lire les systèmes de fichiers RAID). Cependant, la fonction grub_diskfilter_write
génère une erreur GRUB_ERR_NOT_IMPLEMENTED_YET
.
Pourquoi utiliser quick_boot=0
résout le problème? Et pourquoi est-ce la mauvaise solution?
Si vous regardez une fois de plus dans le code /etc/grub.d/00_header
, vous verrez que le défaut recordfail présenté n'est utilisé que lorsque quick_boot=1
. Ainsi, passer de quick_boot
de 1 à 0 désactive la fonctionnalité recordfail et désactive les écritures dans la partition RAID / LVM.
Cependant, de nombreuses autres fonctionnalités seront également désactivées (exécutez grep \$quick_boot /etc/grub.d/*
et vous verrez). Plus encore, si un jour vous changez votre répertoire /boot/grub
en dehors du RAID / LVM, la fonction recordfail sera toujours désactivée.
En résumé, cette solution désactive inutilement les fonctionnalités, et ce n'est pas générique.
Quelle est la bonne solution?
La solution appropriée doit envisager de désactiver les instructions save_env
lorsque GRUB se trouve dans des partitions LVM ou RAID.
Un correctif a été proposé dans le système Debian Bug Tracker pour mettre en œuvre cette solution. Il se trouve dans le lien
.
L'idée derrière ce correctif est:
- Exécutez une commande
grub-probe --target=abstraction "${grubdir}"
pour obtenir le type de modules d'abstraction que GRUB utilise pour lire / écrire des fichiers dans le répertoire /boot/grub
;
- Si GRUB utilise le module
diskfilter
ou lvm
, ignorez l'instruction recordfail save_env
et écrivez un commentaire approprié dans le fichier /boot/grub/grub.cfg
;
- Par exemple,
# GRUB lacks write support for /dev/md0, so recordfail support is disabled.
Comment appliquer la bonne solution?
Si vous ne voulez pas attendre que ce correctif soit appliqué par les gars d'Ubuntu / Debian dans le code officiel, vous pouvez utiliser mon correctif 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