不支持Diskfilter写入>什么触发此错误?

离开Grub菜单时和Ubuntu启动画面之前会出现此消息。

如何解决问题以清除消息?

这是什么意思?

error: Diskfilter writes are not supported 

系统启动,似乎工作得很好。

这是一个BUG!

这是在最新版本的Ubuntu Server LTS(Ubuntu Server 14.04 LTS)中发生的错误,当您在LVM或RAID分区内创建启动分区(或根分区,当启动分区不存在时) 。

您可以在Ubuntu Launchpad中获得有关此错误的更多信息: Bug#1274320“错误:不支持diskfilter写入” 。

更新:此错误已在Ubuntu Server 14.04和一些较新的Ubuntu版本中修复。 可能,您只需要运行apt-get upgrade

为什么会出现这个错误?

系统启动时,GRUB在/boot/grub/grubenv读取( load_env )数据。 该文件称为GRUB Environment Block 。

从GRUB手册:

能够记住从一次启动到下一次启动的少量信息通常很有用。

[…]

在引导时,load_env命令(请参阅load_env)从中加载环境变量,save_env(请参阅save_env)命令将环境变量保存到它。

[…]

grub-mkconfig使用此工具来实现GRUB_SAVEDEFAULT

此行为可以在/etc/grub.d/00_headerupdate-grub使用此文件生成/boot/grub/grub.cfg文件):

 if [ -s $prefix/grubenv ]; then set have_grubenv=true load_env fi 

问题是save_env语句仅适用于简单安装(您无法在RAID或LVM磁盘内运行save_env )。 从GRUB手册:

出于安全原因,此存储仅在安装在普通磁盘(无LVM或RAID),使用非校验和文件系统(无ZFS)以及使用BIOS或EFIfunction(无ATA,USB或IEEE1275)时可用。

GRUB recordfailfunction使用save_env语句来更新recordfail状态(请参阅Ubuntu帮助 – Grub 2 ,“上次启动失败或启动进入恢复模式”部分)。 但是,在Ubuntu 14.04(以及最近的Debian版本)中,即使GRUB安装在LVM或RAID中,也会使用save_env语句(在recordfailfunction内)。

我们在/etc/grub.d/00_header看到104到124之间的行:

 if [ "$quick_boot" = 1 ]; then [...] case "$FS" in btrfs | cpiofs | newc | odc | romfs | squash4 | tarfs | zfs) cat < 

当使用不受支持的文件系统(btrfs,zfs等)时,GRUB正确跳过recordfailfunction,但它不会随时跳过LVM和RAID

GRUB如何保护自己不在RAID和LVM内部写入?

要在文件系统中正确读/写,GRUB会加载适当的模块。

GRUB使用RAID分区中的diskfilter模块( insmod diskfilter )和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 。 因此,将quick_boot从1更改为0会禁用recordfailfunction,并禁用RAID / LVM分区中的写入。

但是,它也会禁用许多其他function(运行grep \$quick_boot /etc/grub.d/* ,你会看到)。 更多的是,如果有一天您将/boot/grub目录更改为RAID / LVM外部,则recordfailfunction仍将被禁用。

总而言之,此解决方案不必要地禁用function,并且它不是通用的。

什么是正确的解决方案?

当GRUB在LVM或RAID分save_env时,正确的解决方案应考虑禁用save_env语句。

在Debian Bug Tracker系统中提出了一个补丁来实现这个解决方案。 它可以在以下url找到: https : //bugs.debian.org/cgi-bin/bugreport.cgi?video = 754921

这个补丁背后的想法是:

  • 运行grub-probe --target=abstraction "${grubdir}"命令以获取GRUB用于读取/写入/boot/grub目录中文件的抽象模块类型;
  • 如果GRUB使用diskfilterlvm模块,请跳过recordfail 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 

我认为这个错误是因为raidLVM分区而发生的。

对于此问题的临时修复:

编辑: /etc/grub.d/10_linux

'quick_boot="1"' with 'quick_boot="0"'

然后 :

 sudo update-grub