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

RCF*_*RCF 90 boot grub2 14.04

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

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

这是什么意思?

error:  Diskfilter writes are not supported
Run Code Online (Sandbox Code Playgroud)

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

Rar*_*tas 148

这是一个BUG!

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

您可以在 Ubuntu Launchpad 中获取有关此错误的更多信息:Bug #1274320 "Error: diskfilter writes are not supported"

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

为什么会出现这个bug?

系统启动时,GRUB 读取 ( load_env) 中的数据/boot/grub/grubenv。该文件称为GRUB 环境块

从 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
Run Code Online (Sandbox Code Playgroud)

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

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

GRUB recordfail功能使用该save_env语句来更新 recordfail 状态(请参阅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
Run Code Online (Sandbox Code Playgroud)

GRUB 在使用不受支持的文件系统(btrfs、zfs 等)时会正确跳过记录失败功能,但在任何时候都不会跳过 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
Run Code Online (Sandbox Code Playgroud)

我在这里粘贴代码(从 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");
}
Run Code Online (Sandbox Code Playgroud)

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更改为 0 会禁用记录失败功能,并禁用 RAID/LVM 分区中的写入。

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

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

什么是正确的解决方案?

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 使用diskfilterorlvm模块,则跳过 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
Run Code Online (Sandbox Code Playgroud)

  • 哇。谢谢你。如果有“本月最佳答案”功能,我会投给你的。此外,您应该获得“无 BS”奖。这是真正提供价值的文章,并且与论坛相比,在该站点网络之间产生了巨大的差异。 (8认同)
  • 嗨@ClassStacker,我总结了答案!它很大,很多人很难理解 :p 它仍然很大,但至少我把它分成了几部分。所以现在您只能查看感兴趣的部分。 (6认同)
  • 7年过去了,这还是一个bug吗? (3认同)

nux*_*nux 34

我认为这个错误是由于raidLVM分区造成的。

对于此问题的临时修复:

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

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

然后 :

sudo update-grub
Run Code Online (Sandbox Code Playgroud)

  • @RCF-U14.04 1) 不,我不必。只需单击“添加评论”-&gt;“帮助”即可了解“帖子作者将始终收到您的评论通知”。2)我想知道(来自nux)为什么这可以解决问题,特别是考虑到Rarylson Freitas的广泛回答。但如果你能回答这个问题,请随意这样做。 (2认同)