不支持磁盘过滤器写入>什么原因引发此错误?

不支持磁盘过滤器写入>什么原因引发此错误?

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

我该如何修复该问题以清除该消息?

这是什么意思呢?

error:  Diskfilter writes are not supported

系统启动并且看上去运行正常。

答案1

这是一个 BUG!

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

您可以在 Ubuntu Launchpad 中获得有关此错误的更多信息:错误 #1274320“错误:不支持磁盘过滤器写入”

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

为什么会出现这个错误?

系统启动时,GRUB 会读取load_env中的数据/boot/grub/grubenv。这个文件叫做GRUB 环境块

来自 GRUB 手册:

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

[...]

在启动时,load_env 命令(参见 load_env)从中加载环境变量,save_env(参见 save_env)命令将环境变量保存到其中。

[...]

grub-mkconfig使用此功能实现GRUB_SAVEDEFAULT

/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语句仅在简单安装中有效(您无法save_env在 RAID 或 LVM 磁盘内运行)。摘自 GRUB 手册:

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

GRUB記錄失敗功能使用该save_env语句来更新记录失败状态(请参阅Ubuntu 帮助 - Grub 2,“上次启动失败或启动进入恢复模式”一节)。然而,在 Ubuntu 14.04(以及最近的 Debian 版本)中,save_env即使 GRUB 安装在 LVM 或 RAID 中,也会使用该语句(位于 recordfail 功能内)。

让我们看看从 104 到 124 行/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

在使用不受支持的文件系统(btrfs、zfs 等)时,GRUB 正确地跳过了 recordfail 功能,但是它不会在任何时候跳过 LVM 和 RAID

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

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

GRUB 使用磁盘过滤器RAID 分区中的模块(insmod diskfilter),以及lvmLVM 分区中的模块。

让我们看看读/写的实现磁盘过滤器模块:

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,您将看到 recordfail 功能仅在 时使用quick_boot=1。因此,quick_boot从 1 更改为 0 会禁用 recordfail 功能,并禁用 RAID/LVM 分区中的写入。

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

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

正确的解决方案是什么?

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

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

此补丁背后的想法是:

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

答案2

我认为发生此错误的原因是袭击或者逻辑卷管理器分割 。

暂时修复此问题:

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

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

然后 :

sudo update-grub

答案3

此错误不再是由于 bug 导致的,因为我几天前在我的 Debian 12 服务器上遇到了此错误。不过Rarylson Freitas 的回答涵盖了它,它提到它是一个 Ubuntu 错误,但实际的根本原因却被埋没。

根本原因:您设置了 GRUB 来为您记住某些内容,但没有提供固定的、非校验和的文件系统分区用于存储。

通常,为了让 GRUB 记住你上次的菜单选择,你需要这样做

GRUB_SAVEDEFAULT=true

在您的 中/etc/default/grub。要实现这一点,GRUB 需要将选择信息写入/保存在某处,即永久磁盘上的某个位置。 info grub environment 'environment block'状态

GRUB 提供了一个“环境块”,可用于保存少量状态。

...

环境块是一个预分配的 1024 字节文件,通常位于“/boot/grub/grubenv”中(尽管您不应该假设这一点)。

...

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

/boot/grub我创建了一个位于LVM 逻辑卷上的分区方案并出现此错误。

当我将其移至/boot固定(ext4)分区(并修复相应的/etc/fstab条目)时,问题就得到了解决。

GRUB:2.12

相关内容