É um BUG!
Este é um bug que ocorre na versão mais recente do Ubuntu Server LTS (Ubuntu Server 14.04 LTS), quando você cria a partição de inicialização (ou a partição raiz, quando a partição de inicialização não existe) dentro de um LVM ou uma partição RAID.
Você pode obter mais informações sobre este bug no Ubuntu Launchpad: Bug # 1274320 "Erro: diskfilter as gravações não são suportadas ".
Atualização: Esse bug já foi corrigido no Ubuntu Server 14.04 e em algumas versões mais recentes do Ubuntu. Provavelmente, você só precisa executar apt-get upgrade
.
Por que esse bug ocorre?
Quando o sistema está inicializando, o GRUB lê os dados ( load_env
) em /boot/grub/grubenv
. Este arquivo é chamado de Bloco de ambiente do GRUB .
Do Manual do 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 implementGRUB_SAVEDEFAULT
Esse comportamento pode ser encontrado em /etc/grub.d/00_header
( update-grub
usa esse arquivo para gerar o arquivo /boot/grub/grub.cfg
):
if [ -s $prefix/grubenv ]; then
set have_grubenv=true
load_env
fi
O problema é que a instrução save_env
só funciona em instalações simples (você não pode executar save_env
dentro de um disco RAID ou LVM). Do manual do 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).
O recurso recordfail do GRUB usa a instrução save_env
para atualizar o estado recordfail (consulte Ajuda do Ubuntu - Grub 2 , "Última inicialização falhada ou inicialização no modo de recuperação" seção). No entanto, no Ubuntu 14.04 (e em versões recentes do Debian), a instrução save_env
(dentro do recurso recordfail) é usada mesmo se o GRUB estiver instalado em um LVM ou um RAID.
Vamos ver as linhas de 104 a 124 em /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
O GRUB ignora corretamente o recurso recordfail ao usar sistemas de arquivos não suportados (btrfs, zfs, etc), mas ele não ignora o LVM e o RAID a qualquer momento .
Como o GRUB se protege de escrever dentro de RAID e LVM?
Para ler / escrever corretamente em um sistema de arquivos, o GRUB carrega um módulo apropriado.
O GRUB usa o módulo diskfilter ( insmod diskfilter
) em partições RAID e o módulo lvm em partições LVM.
Vamos ver a implementação de leitura / gravação do módulo diskfilter :
apt-get source grub2
vim grub2-2.02~beta2/grub-core/disk/diskfilter.c
Estou colando o código aqui (linhas de 808 a 823). O aviso mostrado nesta pergunta aparece na linha 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");
}
A função grub_diskfilter_read
é implementada (e o GRUB pode ler sistemas de arquivos RAID). No entanto, a função grub_diskfilter_write
gera um erro GRUB_ERR_NOT_IMPLEMENTED_YET
.
Por que usar quick_boot=0
resolve o problema? E por que é a solução errada?
Se você olhar mais uma vez no código /etc/grub.d/00_header
, verá que o recordfail em destaque é usado apenas quando quick_boot=1
. Portanto, alterar quick_boot
de 1 para 0 desativa o recurso recordfail e desativa as gravações na partição RAID / LVM.
No entanto, ele também desativará muitos outros recursos (execute grep \$quick_boot /etc/grub.d/*
e você verá). Mais ainda, se um dia você alterar o diretório /boot/grub
para fora do RAID / LVM, o recurso recordfail ainda estará desabilitado.
Em suma, essa solução desativa recursos desnecessariamente e não é genérica.
Qual é a solução correta?
A solução correta deve considerar desativar as instruções save_env
quando o GRUB estiver dentro de partições LVM ou RAID.
Um patch foi proposto no sistema Debian Bug Tracker para implementar esta solução. Pode ser encontrado em: link
A ideia por trás deste patch é:
- Execute um comando
grub-probe --target=abstraction "${grubdir}"
para obter o tipo de módulos de abstração que o GRUB usa para ler / gravar arquivos no diretório/boot/grub
; - Se o GRUB usar o módulo
diskfilter
oulvm
, ignore a instrução recordfailsave_env
e escreva um comentário apropriado no arquivo/boot/grub/grub.cfg
;- Por exemplo,
# GRUB lacks write support for /dev/md0, so recordfail support is disabled.
- Por exemplo,
Como aplicar a solução correta?
Se você não quiser esperar que este patch seja aplicado pelos caras do Ubuntu / Debian no código oficial, você pode usar meu patch 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