C'est un BUG !
Il s'agit d'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) à l'intérieur d'une partition LVM ou RAID.
Vous pouvez obtenir plus d'informations sur ce bogue dans Ubuntu Launchpad : Bogue n° 1274320 "Erreur : les écritures du diskfilter ne sont pas supportées". .
Mise à jour : Ce bogue est déjà corrigé dans Ubuntu Server 14.04 et certaines versions plus récentes d'Ubuntu. Probablement, il vous suffit d'exécuter apt-get upgrade
.
Pourquoi ce bogue se produit-il ?
Lorsque le système démarre, Grub lit ( load_env
) dans /boot/grub/grubenv
. Ce fichier est appelé Grub Bloc d'environnement .
Du manuel Grub :
Il est souvent utile de pouvoir se souvenir d'une petite quantité d'informations d'un démarrage à l'autre.
[...]
Au moment du démarrage, la commande load_env (voir load_env) charge les variables d'environnement à partir de celui-ci, et la commande save_env (voir save_env) enregistre les variables d'environnement dans celui-ci.
[...]
grub-mkconfig
utilise ce dispositif pour mettre en œuvre GRUB_SAVEDEFAULT
Ce comportement peut être fondé dans /etc/grub.d/00_header
( update-grub
utilise ce fichier pour générer le /boot/grub/grub.cfg
) :
if [ -s $prefix/grubenv ]; then
set have_grubenv=true
load_env
fi
Le problème est que le save_env
ne fonctionne que dans les installations simples (vous ne pouvez pas exécuter la commande save_env
à l'intérieur d'un disque RAID ou LVM). Extrait du manuel Grub :
Pour des raisons de sécurité, ce stockage n'est disponible que lorsqu'il est installé sur un disque ordinaire (pas de LVM ou RAID), en utilisant un système de fichiers sans somme de contrôle (pas de ZFS) et en utilisant les fonctions BIOS ou EFI (pas d'ATA, USB ou IEEE1275).
Le Grub recordfail utilise la fonction save_env
pour mettre à jour l'état d'échec de l'enregistrement (voir Ubuntu Help - Grub 2 , section "Last Boot Failed or Boot into Recovery Mode"). Cependant, dans Ubuntu 14.04 (et dans les versions récentes de Debian), la fonction save_env
(à l'intérieur de la fonction 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 saute correctement la fonction recordfail lors de l'utilisation de systèmes de fichiers non supportés (btrfs, zfs, etc.), mais il ne saute pas LVM et 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 l'option Filtre à disque module ( insmod diskfilter
) dans les partitions RAID, et le lvm dans les partitions LVM.
Voyons l'implémentation en lecture/écriture de la fonction Filtre à disque module :
apt-get source grub2
vim grub2-2.02~beta2/grub-core/disk/diskfilter.c
Je colle le code ici (lignes de 808 à 823). L'avertissement montré 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");
}
El grub_diskfilter_read
est implémentée (et Grub peut lire les systèmes de fichiers RAID). Cependant, la fonction grub_diskfilter_write
soulève un GRUB_ERR_NOT_IMPLEMENTED_YET
erreur.
Pourquoi l'utilisation quick_boot=0
résoudre le problème ? Et pourquoi est-ce la mauvaise solution ?
Si vous regardez encore une fois dans le /etc/grub.d/00_header
vous verrez que la fonctionnalité recordfail n'est utilisée que lorsque quick_boot=1
. Donc, en changeant quick_boot
de 1 à 0 désactive la fonction recordfail, et désactive les écritures dans la partition RAID/LVM.
Cependant, cela désactivera également de nombreuses autres fonctionnalités (run grep \$quick_boot /etc/grub.d/*
et vous verrez). Plus encore, si un jour vous changez votre /boot/grub
à l'extérieur du RAID/LVM, la fonction recordfail sera toujours désactivée.
En résumé, cette solution désactive inutilement des fonctionnalités, et elle n'est pas générique.
Quelle est la bonne solution ?
La solution correcte devrait envisager de désactiver le save_env
lorsque Grub se trouve dans des partitions LVM ou RAID.
Un correctif a été proposé dans le système de suivi des bogues de Debian pour mettre en œuvre cette solution. Il peut être trouvé dans : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=754921
L'idée derrière ce patch est :
- Exécuter un
grub-probe --target=abstraction "${grubdir}"
pour obtenir le type de modules d'abstraction que Grub utilise pour lire/écrire les fichiers dans le fichier /boot/grub
répertoire ;
- Si Grub utilise l'option
diskfilter
o lvm
ignorez le module recordfail save_env
et rédiger un commentaire approprié dans le /boot/grub/grub.cfg
fichier ;
- 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