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

87

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

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

这是什么意思?

error:  Diskfilter writes are not supported

系统启动,似乎工作正常。

    
RCF 18.05.2014 - 01:14

2 答案

144

这是一个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会读取 load_env 中的( /boot/grub/grubenv )数据。此文件名为 GRUB Environment Block

从GRUB手册:

%bl0ck_qu0te%

此行为可以在 /etc/grub.d/00_header 中创建( update-grub 使用此文件生成 /boot/grub/grub.cfg 文件):

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

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

%bl0ck_qu0te%

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

让我们看看 /etc/grub.d/00_header 中的104到124行:

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

当使用不支持的文件系统(btrfs,zfs等)时,GRUB正确地跳过了recordfail功能,但它不会随时跳过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 时使用recordfail feature。因此,将 quick_boot 从1更改为0将禁用recordfail功能,并禁用RAID / LVM分区中的写入。

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

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

什么是正确的解决方案?

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

在Debian Bug Tracker系统中提出了一个补丁来实现这个解决方案。它可以在以下网址找到:链接

这个补丁背后的想法是:

  • 运行 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
    
给出答案 Rarylson Freitas 16.07.2014 - 00:42
33

我认为由于 raid LVM 分区而发生此错误。

暂时解决此问题:

修改: /etc/grub.d/10_linux

替换 'quick_boot="1"' with 'quick_boot="0"'

然后:

sudo update-grub
    
给出答案 nux 18.05.2014 - 02:14

阅读有关标签的其他问题