Bcache

来自 ArchWiki

此文章或章节需要改进语言、wiki 语法或风格。请参阅 Help:Style 以获取参考。

原因: 一些第一人称评论,请参阅 Help:Style。(在 Talk:Bcache 中讨论)

Bcache (块缓存) 允许您使用 SSD 作为另一个块设备(通常是旋转 HDD 或阵列)的读/写缓存(在回写模式下)或读取缓存(直写或绕写)。本文将展示如何使用 Bcache 作为根分区安装 Arch。有关 bcache 本身的介绍,请参阅 bcache 首页。请务必阅读并参考 bcache 手册

提示: Bcache 的替代方案是 LVM 缓存

Bcache 需要将后备设备格式化为 bcache 块设备。在大多数情况下,blocks to-bcache 可以进行就地转换。

此文章或章节已过时。

原因: 2024 年 bcache 与 btrfs 导致损坏的任何来源?链接的博客没有额外的详细信息(在 Talk:Bcache 中讨论)
警告
  • 请务必先备份任何重要数据。
  • Bcache 和 btrfs 可能会导致文件系统损坏。请访问 这篇文章 以获取更多信息。Btrfs wiki 报告称,它已在内核 3.19+ 中修复 [1]

在现有系统上设置已缓存的 btrfs 文件系统

警告: make-bcache 不会 导入现有驱动器或分区 – 它会重新格式化它。

准备工作

安装 bcache-toolsAUR

使用 fdisk 在 SSD 和硬盘上创建适当的分区,以保存缓存和后备数据。

提示: 可以在单个驱动器上创建多个分区。这允许在提交之前测试复杂的设置。请注意,当驱动器发生故障时,所有数据都将丢失。这也会由于不利的访问模式而降低驱动器的性能。

情况:1 个硬盘和 1 个读取缓存 SSD

警告
  • 当单个硬盘发生故障时,所有数据都将丢失。
  • 不要启用写入缓存,因为这可能会在 SSD 发生故障时导致数据丢失
+--------------+
| btrfs /mnt   |
+--------------+
| /dev/Bcache0 |
+--------------+
| Cache        |
| /dev/sdk1    |
+--------------+
| Data         |
| /dev/sdv1    |
+--------------+

1. 格式化后备设备(这通常是您的机械硬盘)。后备设备可以是整个设备、分区或任何其他标准块设备。这将创建 /dev/bcache0

# make-bcache -B /dev/sdv1

2. 格式化缓存设备(这通常是您的 SSD)。缓存设备可以是整个设备、分区或任何其他标准块设备

# make-bcache -C /dev/sdk1

在此示例中,使用了默认的块和 bucket 大小 512B 和 128kB。块大小应与后备设备的扇区大小匹配,通常为 512 或 4k。bucket 大小应与缓存设备的擦除块大小匹配,目的是减少写入放大。例如,使用具有 4k 扇区的 HDD 和具有 2MB 擦除块大小的 SSD,此命令将如下所示

# make-bcache --block 4k --bucket 2M -C /dev/sdk1
注意: 您可能需要省略 --block 4k 选项,请参阅 无法将缓存设备连接到后备设备

3. 获取缓存设备的 uuid

# bcache-super-show /dev/sdk1 | grep cset
cset.uuid		f0e01318-f4fd-4fab-abbb-d76d870503ec

4. 将缓存设备注册到您的后备设备。将示例 uuid 替换为您的缓存的 uuid。Udev 规则将在重启时处理此问题,并且只需执行一次。

# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache0/bcache/attach

5. 创建 btrfs 文件系统。

# mkfs.btrfs /dev/bcache0

6. 挂载文件系统

# mount /dev/bcache0 /mnt

7. 如果您希望在 initcpio 期间(即您在启动过程中的某个时刻需要它)可以使用此分区,则需要在 /etc/mkinitcpio.conf 中的模块数组中添加“bcache”,并在 block 和 filesystems 之间的列表中添加“bcache”挂钩。然后您必须重新生成 initramfs

情况:4 个硬盘和 1 个读取缓存 SSD

警告
  • 不要启用写入缓存,因为这可能会在 SSD 发生故障时导致数据丢失
+-----------------------------------------------------------+
|                         btrfs /mnt                        |
+--------------+--------------+--------------+--------------+
| /dev/Bcache0 | /dev/Bcache1 | /dev/Bcache2 | /dev/Bcache3 |
+--------------+--------------+--------------+--------------+
|                           Cache                           |  
|                         /dev/sdk1                         |
+--------------+--------------+--------------+--------------+
| Data         | Data         | Data         | Data         |
| /dev/sdv1    | /dev/sdw1    | /dev/sdx1    | /dev/sdy1    |
+--------------+--------------+--------------+--------------+

1. 格式化后备设备(这些通常是您的机械硬盘)。后备设备可以是整个设备、分区或任何其他标准块设备。这将创建 /dev/bcache0、/dev/bcache1、/dev/bcache2 和 /dev/bcache3

# make-bcache -B /dev/sdv1
# make-bcache -B /dev/sdw1
# make-bcache -B /dev/sdx1
# make-bcache -B /dev/sdy1

2. 格式化缓存设备(这通常是您的 SSD)。缓存设备可以是整个设备、分区或任何其他标准块设备。只有一个缓存设备可以添加到一组后备设备。

# make-bcache -C /dev/sdk1

3. 获取缓存设备的 uuid

# bcache-super-show /dev/sdk1 | grep cset
cset.uuid		f0e01318-f4fd-4fab-abbb-d76d870503ec

4. 将缓存设备注册到您的后备设备。将示例 uuid 替换为您的缓存的 uuid。

# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache0/bcache/attach
# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache1/bcache/attach
# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache2/bcache/attach
# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache3/bcache/attach

5. 创建 btrfs 文件系统。数据和元数据都在阵列中存储两次,因此当单个硬盘发生故障时不会丢失数据。-L 参数定义文件系统的标签。

# mkfs.btrfs -L STORAGE -f -d raid1 -m raid1 /dev/bcache0 /dev/bcache1 /dev/bcache2 /dev/bcache3 

6. 挂载文件系统

# mount /dev/bcache0 /mnt

情况:3 个硬盘和 3 个读/写缓存 SSD

警告
  • 每个 HDD 都需要自己的 SSD,以避免在回写模式下的 SSD 发生故障时数据丢失。
+--------------------------------------------+
|                  btrfs /mnt                |
+--------------+--------------+--------------+
| /dev/Bcache0 | /dev/Bcache1 | /dev/Bcache2 |
+--------------+--------------+--------------+
| Cache        | Cache        | Cache        |  
| /dev/sdk1    | /dev/sdl1    | /dev/sdm1    |
+--------------+--------------+--------------+
| Data         | Data         | Data         |
| /dev/sdv1    | /dev/sdw1    | /dev/sdx1    |
+--------------+--------------+--------------+

1. 格式化后备设备(这些通常是您的机械硬盘)。后备设备可以是整个设备、分区或任何其他标准块设备。这将创建 /dev/bcache0、/dev/bcache1 和 /dev/bcache2。

# make-bcache -B /dev/sdv1
# make-bcache -B /dev/sdw1
# make-bcache -B /dev/sdx1

2. 格式化缓存设备(这些通常是您的 SSD)。缓存设备可以是整个设备、分区或任何其他标准块设备。为了避免在 SSD 发生故障时数据丢失,如果后备设备处于回写模式,则每个后备设备都需要自己的 SSD。直写和绕写模式下的缓存 SSD 可以由多个后备设备共享,因为它们在发生故障时不会导致数据丢失。

# make-bcache -C /dev/sdk1
# make-bcache -C /dev/sdl1
# make-bcache -C /dev/sdm1

3. 获取缓存设备的 uuid

# bcache-super-show /dev/sdk1 | grep cset
cset.uuid		f0e01318-f4fd-4fab-abbb-d76d870503ec
# bcache-super-show /dev/sdl1 | grep cset
cset.uuid		4b05ce02-19f4-4cc6-8ca0-1f765671ceda
# bcache-super-show /dev/sdm1 | grep cset
cset.uuid		75ff0598-7624-46f6-bcac-c27a3cf1a09f

4. 将缓存设备注册到您的后备设备。将示例 uuid 替换为您的缓存的 uuid。

# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache0/bcache/attach
# echo 4b05ce02-19f4-4cc6-8ca0-1f765671ceda > /sys/block/bcache1/bcache/attach
# echo 75ff0598-7624-46f6-bcac-c27a3cf1a09f > /sys/block/bcache2/bcache/attach

5. 启用回写模式

此文章或章节已过时。

原因: 官方文档或内核文档中没有此类警告。以下内容的任何来源?(在 Talk:Bcache 中讨论)
警告
  • Bcache 写入缓存可能会导致 btrfs 文件系统发生灾难性故障。
  • Btrfs 假定底层设备按顺序执行写入,但 bcache 回写可能会违反该假设,从而导致使用它的 btrfs 文件系统崩溃。
  • 每个缓存层或写入缓存都会增加在断电时丢失数据的风险。
  • 使用带有 btrfs 的回写模式 bcache,风险自负。
# echo writeback > /sys/block/bcache0/bcache/cache_mode
# echo writeback > /sys/block/bcache1/bcache/cache_mode
# echo writeback > /sys/block/bcache2/bcache/cache_mode

6. 创建 btrfs 文件系统。数据和元数据都在阵列中存储两次,因此当单个硬盘发生故障时不会丢失数据。-L 参数定义文件系统的标签。

# mkfs.btrfs -L STORAGE -f -d raid1 -m raid1 /dev/bcache0 /dev/bcache1 /dev/bcache2

7. 挂载文件系统

# mount /dev/bcache0 /mnt

情况:5 个硬盘和 3 个缓存 SSD

警告
  • 回写模式下的每个缓存设备都必须仅用于缓存单个后备驱动器,以避免在该 SSD 发生故障时数据丢失。直写和绕写 SSD 可以共享。
+--------------------------------------------------------------------------+
|                                btrfs /mnt                                |
+--------------+--------------+--------------+--------------+--------------+
| /dev/Bcache0 | /dev/Bcache1 | /dev/Bcache2 | /dev/Bcache3 | /dev/Bcache4 |
+--------------+--------------+--------------+--------------+--------------+
| WriteB Cache |     Writethrough or writearound Cache      | WriteB Cache |  
| /dev/sdk1    |                 /dev/sdl1                  | /dev/sdm1    |
+--------------+--------------+--------------+--------------+--------------+
| Data         | Data         | Data         | Data         | Data         |
| /dev/sdv1    | /dev/sdw1    | /dev/sdx1    | /dev/sdy1    | /dev/sdz1    |
+--------------+--------------+--------------+--------------+--------------+

1. 格式化后备设备(这些通常是您的机械硬盘)。后备设备可以是整个设备、分区或任何其他标准块设备。这将创建 /dev/bcache0、/dev/bcache1、/dev/bcache2、/dev/bcache3 和 /dev/bcache4。

# make-bcache -B /dev/sdv1
# make-bcache -B /dev/sdw1
# make-bcache -B /dev/sdx1
# make-bcache -B /dev/sdy1
# make-bcache -B /dev/sdz1

2. 格式化缓存设备(这些通常是您的 SSD)。缓存设备可以是整个设备、分区或任何其他标准块设备。为了避免在 SSD 发生故障时数据丢失,如果后备设备处于回写模式,则每个后备设备都需要自己的 SSD。直写和绕写模式下的缓存 SSD 可以由多个后备设备共享,因为它们在发生故障时不会导致数据丢失。

# make-bcache -C /dev/sdk1
# make-bcache -C /dev/sdl1
# make-bcache -C /dev/sdm1

3. 获取缓存设备的 uuid

# bcache-super-show /dev/sdk1 | grep cset
cset.uuid		f0e01318-f4fd-4fab-abbb-d76d870503ec
# bcache-super-show /dev/sdl1 | grep cset
cset.uuid		4b05ce02-19f4-4cc6-8ca0-1f765671ceda
# bcache-super-show /dev/sdm1 | grep cset
cset.uuid		75ff0598-7624-46f6-bcac-c27a3cf1a09f

4. 将缓存设备注册到您的后备设备。将示例 uuid 替换为您的缓存的 uuid。

# echo f0e01318-f4fd-4fab-abbb-d76d870503ec > /sys/block/bcache0/bcache/attach
# echo 4b05ce02-19f4-4cc6-8ca0-1f765671ceda > /sys/block/bcache1/bcache/attach
# echo 4b05ce02-19f4-4cc6-8ca0-1f765671ceda > /sys/block/bcache2/bcache/attach
# echo 4b05ce02-19f4-4cc6-8ca0-1f765671ceda > /sys/block/bcache3/bcache/attach
# echo 75ff0598-7624-46f6-bcac-c27a3cf1a09f > /sys/block/bcache4/bcache/attach

5. 在非共享缓存上启用回写模式

# echo writeback > /sys/block/bcache0/bcache/cache_mode
# echo writeback > /sys/block/bcache4/bcache/cache_mode

6. 创建 btrfs 文件系统。数据和元数据都在阵列中存储两次,因此当单个硬盘发生故障时不会丢失数据。-L 参数定义文件系统的标签。

# mkfs.btrfs -L STORAGE -f -d raid1 -m raid1 /dev/bcache0 /dev/bcache1 /dev/bcache2 /dev/bcache3 /dev/bcache4

7. 挂载文件系统

# mount /dev/bcache0 /mnt

Bcache 管理

1. 检查一切是否已正确设置

# cat /sys/block/bcache0/bcache/state

输出可以是

  • no cache:这意味着您尚未将缓存设备连接到您的后备 bcache 设备
  • clean:这意味着一切正常。缓存是干净的。
  • dirty:这意味着一切设置正常,并且您已启用回写,并且缓存是脏的。
  • inconsistent:您遇到麻烦了,因为后备设备与缓存设备不同步

您可以拥有一个与没有连接缓存设备的后备设备关联的 /dev/bcache0 设备。这意味着所有 I/O(读/写)都直接传递到后备设备(直通模式)

2. 查看正在使用的缓存模式

# cat /sys/block/bcache0/bcache/cache_mode
[writethrough] writeback writearound none

在上面的示例中,启用了直写模式。

3. 显示有关已缓存设备的信息

# bcache-super-show /dev/sdXY

4. 停止后备设备

# echo 1 > /sys/block/sdX/sdX[Y]/bcache/stop

5. 分离缓存设备

# echo 1 > /sys/block/sdX/sdX[Y]/bcache/detach

6. 安全移除缓存设备

# echo cache-set-uuid > /sys/block/bcache0/bcache/detach

7. 释放连接的设备

# echo 1 > /sys/fs/bcache/cache-set-uuid/stop

安装到 bcache 设备

1. 从安装盘启动(最低 2013.08.01)。

2. 安装 bcache-toolsAUR

3. 分区您的 HDD

注意: 尽管 Grub2 可能不支持 bcache(如下所述),但它完全支持 UEFI。 因此,只要 Linux 内核正确处理您的启动设备所需的模块已编译到内核中,或者包含在 initramfs 中,并且您可以将这些文件包含在其中,则可以省略下面描述的单独启动分区,而支持 FAT EFI 系统分区。 有关更多信息,请参阅 GRUB 和/或 UEFI

grub 无法处理 bcache,因此您至少需要 2 个分区(boot 分区和一个用于 bcache 后端设备的分区)。 如果您正在使用 UEFI,您还需要一个 EFI 系统分区 (ESP)。 例如:

   1            2048         2099199   1024.0 MiB  EF00  EFI system partition
   2         2099200         4196351   1024.0 MiB  EA00  arch_boot
   3         4196352       499998719   236.4 GiB   8300  bcache_backing
注意: 此示例没有交换文件/分区。 要在缓存上使用交换分区,请在步骤 7 中使用 LVM。 要在缓存外部使用交换分区,请务必立即创建一个交换分区。

4. 将您的 HDD 配置为 bcache 后端设备。

# make-bcache -B /dev/sda3
注意
  • 在准备任何启动盘时,了解您可能做出的任何决定的影响非常重要。 请仔细阅读并再次阅读您选择的启动加载程序/-管理器的文档,并认真考虑它可能与 bcache 有何关联。
  • 如果所有关联的磁盘都如下所示一次性分区,则 bcache 将自动将“ -B 后端存储”附加到“ -C ssd 缓存”,并且步骤 5 是不必要的。
# make-bcache -B /dev/sd? /dev/sd? -C /dev/sd?

您现在拥有一个 /dev/bcache0 设备。

5. 配置您的 SSD

将 SSD 格式化为缓存设备,并将其链接到后端设备

# make-bcache -C /dev/sdb
# echo /dev/sdb > /sys/fs/bcache/register 
# echo UUID__from_previous_command > /sys/block/bcache0/bcache/attach
注意: 如果 UUID 被遗忘,可以在缓存设备注册后使用 ls /sys/fs/bcache/ 找到它。

6. 格式化 bcache 设备。 如果您想划分 /dev/bcache0 设备的使用方式(例如,用于单独的 //home/var 等),请使用 LVM 或 btrfs 子卷。

# mkfs.btrfs /dev/bcache0
# mount /dev/bcache0 /mnt/
# btrfs subvolume create /mnt/root
# btrfs subvolume create /mnt/home
# umount /mnt

如果您愿意,甚至可以在其上设置 LUKS,例如使用 cryptsetup。 在 'cryptdevice' 内核选项中引用 bcache 设备是可以正常工作的。

7. 准备安装挂载点

# mkfs.ext4 /dev/sda2
# mkfs.fat -F 32 /dev/sda1

现在安装 arch-install-scripts 软件包。 然后

# mount /dev/bcache0 -o subvol=root,compress=lzo /mnt/
# mount --mkdir /dev/bcache0 -o subvol=home,compress=lzo /mnt/home
# mount --mkdir /dev/sda2 /mnt/boot
# mount --mkdir /dev/sda1 /mnt/efi

8. 按照 安装指南 正常安装系统,但以下情况除外:

在您编辑 /etc/mkinitcpio.conf 并运行 mkinitcpio -p linux 之前

  • 安装 bcache-toolsAUR
  • 编辑 /etc/mkinitcpio.conf
    • 添加 “bcache” 模块
    • 在 block 和 filesystem 钩子之间添加 “bcache” 钩子
注意: 如果您出于任何原因在重启后想从安装介质打开后端设备,则必须手动注册它。 确保 bcache 模块已加载,然后将相关设备 echo 到 /sys/bcache/register。 您应该使用 dmesg 查看这是否有效。

从安装盘访问

以下是如何从安装盘访问在安装盘启动之前存在的 bcache 分区。 启动安装盘并从 AUR 安装 bcache-toolsAUR,就像上一节中一样。 然后,将模块添加到内核

# modprobe bcache

您的设备不会立即出现在 /dev/bcache*。 要强制内核查找它,请告诉它重新读取分区表

# partprobe

现在,/dev/bcache* 应该存在,您可以从此处继续挂载、重新格式化等操作。

要在不配置互联网和安装 bcache-toolsAUR 的情况下启动缓存,请像以前一样加载内核模块——它包含在主线内核中。 然后,通过注册所有从属设备来启动缓存

# echo /dev/sdX > /sys/fs/bcache/register
# echo /dev/sdY > /sys/fs/bcache/register
# ...

bcache 设备将在最后一个必需的从属设备注册后立即出现。

writethrough 后端设备可以在不注册任何缓存的情况下启动。 如果有很多这样的设备并且您很着急,或者某些缓存由于某种原因无法访问,则可以这样做。 如上所述注册设备,然后启动它

# echo 1 > /sys/block/sdX/bcache/running

Bcache 实际上并未分离任何缓存,如果注册了任何缓存设备,它仍然会添加它们。 此命令将在 writeback 后端设备上“起作用”,但会发生大规模数据损坏。 仅当丢失的缓存完全无法恢复时才执行此操作。

配置

警告: 不要启用 discard 选项! 它可能导致无法恢复的损坏。 [2][3]

有许多选项可以配置(例如缓存模式、缓存刷新间隔、顺序写入启发式等)。 这目前通过写入 /sys 中的文件来完成。 请参阅 bcache 用户文档

更改缓存模式是通过将 writethroughwritebackwritearoundnone 之一 echo 到 /sys/block/bcache[0-9]/bcache/cache_mode 来完成的。

请注意,对 /sys 的某些更改是临时的,并且会在重启后恢复(似乎至少 cache_mode 不需要此解决方法)。 要在启动时设置自定义配置,请在 /etc/tmpfiles.d 中创建一个 .conf 文件。 要以持久的方式将 bcache0 的顺序截止值设置为 1 MB 并回写,您可以创建一个文件 /etc/tmpfiles.d/my-bcache.conf,内容如下:

w /sys/block/bcache0/bcache/sequential_cutoff - - - - 1M
w /sys/block/bcache0/bcache/cache_mode        - - - - writeback

情况:阻止对 HDD 的所有写入访问

警告
  • 当硬盘驱动器或 SSD 发生故障时,所有数据都将丢失。
  • 考虑使用 BTRFS RAID 以防止 SSD/HDD 发生故障时数据丢失。

在这种情况下,目标是尽可能使 HDD 保持空闲状态。 这通过使用 SSD 吸收所有写入操作来实现。 只有当 SSD 已满,或者读取的内容不在 SSD 上时,才会激活硬盘驱动器。

启用 writeback 缓存模式

# echo writeback > /sys/block/bcache0/bcache/cache_mode

让 bcache 完全与硬盘驱动器同步。

# echo 0 > /sys/block/bcache0/bcache/writeback_percent

不要让顺序 IO 绕过缓存

# echo 0 > /sys/block/bcache0/bcache/sequential_cutoff 

让 bcache 在上次同步完成后等待一周

# echo $((7*24*60*60)) > /sys/block/bcache0/bcache/writeback_delay

当存在读/写拥塞时,不要让 bcache 绕过缓存

# echo 0 > /sys/fs/bcache/<cache set>/congested_read_threshold_us
# echo 0 > /sys/fs/bcache/<cache set>/congested_write_threshold_us

让 HDD 在 20 分钟后进入睡眠状态

# hdparm -S 240  /dev/$(cat /sys/block/bcache0/bcache/backing_dev_name)
/dev/sdh1:
setting standby to 240 (20 minutes)


First use lsblk to get the device names of the HDD and SSD. In this example /dev/sdh1 is the HDD, /dev/sdc1 is the SSD:
# lsblk -M -s
bcache0   254:0    0 931.5G  0 disk 
   ├─sdc1      8:33   0 111.8G  0 part 
   │ └─sdc     8:32   0 111.8G  0 disk 
   └─sdh1      8:113  0 931.5G  0 part 
     └─sdh     8:112  0 931.5G  0 disk

现在可以使用 Dstat 监视对 bcache 集成员的磁盘访问。

$ dstat -D sdc1,sdh1

高级操作

调整后端设备大小

只要您不移动分区起始位置,就可以调整后端设备的大小。 邮件列表中描述了此过程。 这是一个直接在 bcache0 上使用 btrfs 卷的示例。 对于 LVM 容器或其他文件系统,过程将有所不同。

扩容示例

在此示例中,我将文件系统扩容 4GB。

1. 重启到 Live CD/USB 驱动器(不必启用 bcache),并使用 fdisk、gdisk、parted 或您其他喜欢的工具删除后端分区,并使用相同的起始位置和总大小大 4G 的大小重新创建它。

警告: 不要使用像 GParted 这样的工具,它可能会执行文件系统操作! 它无法识别 bcache 分区,并可能覆盖其中的一部分!!

2. 重启到您的正常安装。 您的文件系统当前将被挂载。 这没关系。 发出命令以将分区大小调整到其最大值。 对于 btrfs,它是

# btrfs filesystem resize max /

对于 ext3/4,它是

# resize2fs /dev/bcache0

缩容示例

在此示例中,我将文件系统缩容 4GB。

1. 禁用 writeback 缓存(切换到 writethrough 缓存)并等待磁盘刷新。

# echo writethrough > /sys/block/bcache0/bcache/cache_mode
$ watch cat /sys/block/bcache0/bcache/state

等待直到状态报告 “clean”。 这可能需要一段时间。

强制将缓存刷新到后端设备

我建议使用

 # echo 0 > /sys/block/bcache0/bcache/writeback_percent

这将在一分钟内将缓存的脏数据刷新到后端设备。

之后使用以下命令恢复该值

# echo 10 > /sys/block/bcache0/bcache/writeback_percent

2. 将已挂载的文件系统缩小大于所需量的值,以确保我们稍后不会意外地裁剪它。 对于 btrfs,它是

# btrfs filesystem resize -5G /

对于 ext3/4,您可以使用 resize2fs,但仅当分区未挂载时才可以使用

$ df -h /home
/dev/bcache0    290G   20G   270G   1% /home
# umount /home
# resize2fs /dev/bcache0 283G

3. 重启到 LiveCD/USB 驱动器(不需要支持 bcache),并使用 fdisk、gdisk、parted 或您其他喜欢的工具删除后端分区,并使用相同的起始位置和总大小小 4G 的大小重新创建它。

警告: 不要使用像 GParted 这样的工具,它可能会执行文件系统操作! 它无法识别 bcache 分区,并可能覆盖其中的一部分!!

4. 重启到您的正常安装。 您的文件系统当前将被挂载。 这没关系。 发出命令以将分区大小调整到其最大值(即我们在步骤 3 中将实际分区缩小到的大小)。 对于 btrfs,它是

# btrfs filesystem resize max /

对于 ext3/4,它是

# resize2fs /dev/bcache0

5. 如果您希望启用 writeback 缓存,请重新启用它

# echo writeback > /sys/block/bcache0/bcache/cache_mode
注意: 如果您非常小心,可以将文件系统缩小到步骤 2 中的确切大小,并避免步骤 4。 但是请注意,许多分区工具并不能完全按照您的意愿执行操作,而是调整请求的分区起始/结束点以在扇区边界上结束。 这可能很难提前计算。

故障排除

/dev/bcache 设备在启动时不存在

如果您被发送到 busy box shell 并出现错误

ERROR: Unable to find root device 'UUID=b6b2d82b-f87e-44d5-bbc5-c51dd7aace15'.
You are being dropped to a recovery shell
    Type 'exit' to try and continue booting

如果后端设备配置为 “writeback” 模式(默认模式为 writearound),则可能会发生这种情况。 在 “writeback” 模式下,/dev/bcache0 设备在缓存设备注册并附加之前不会启动。 注册是每次启动都需要发生的事情,但附加应该只需要完成一次。

要继续启动,请尝试以下操作之一

  • 注册后端设备和缓存设备
# echo /dev/sda3 > /sys/fs/bcache/register
# echo /dev/sdb > /sys/fs/bcache/register

如果 /dev/bcache0 设备现在存在,请键入 exit 并继续启动。 您需要修复您的 initcpio 以确保设备在挂载根设备之前注册。

注意
  • “sh: echo: write error: Invalid argument” 错误意味着设备已注册或未被识别为 bcache 后端设备或缓存。 如果在启动时使用 udev 规则,则只有在找到 bcache 超级块时才应尝试注册设备。
  • 如果由于流氓超级块导致 blkid 和 bcache-probe “不一致”,也可能发生这种情况,如安装步骤 7 中使用 udev 的 69-bcache.rules。 有关可能的解释/解决方案,请参阅 bcache 的 wiki
  • 重新将缓存附加到后端设备

如果缓存设备已注册,则 UUID 为缓存的文件夹应存在于 /sys/fs/bcache 中。 使用该 UUID 并按照以下示例操作

# ls /sys/fs/bcache/
b6b2d82b-f87e-44d5-bbc5-c51dd7aace15     register     register_quiet
# echo b6b2d82b-f87e-44d5-bbc5-c51dd7aace15 > /sys/block/sda/sda3/bcache/attach

如果 /dev/bcache0 设备现在存在,请键入 exit 并继续启动。 您不应该再次执行此操作。 如果问题仍然存在,请在 bcache 邮件列表中提问。

注意: sh: echo: write error: Invalid argument 错误意味着设备已附加。 sh: echo: write error: No such file or directory 错误意味着 UUID 不是有效的缓存(请确保您正确键入了它)。
  • 使缓存无效并强制后端设备在没有缓存的情况下运行。 您可能需要检查一些统计信息,例如 “dirty_data”,以便您了解将丢失多少数据。
# cat /sys/block/sda/sda3/bcache/dirty_data
-3.9M

脏数据是缓存中尚未写入后端设备的数据。 如果您强制后端设备运行,即使您稍后重新附加缓存,这些数据也会丢失。

# cat /sys/block/sda/sda3/bcache/running
0
# echo 1 > /sys/block/sda/sda3/bcache/running

/dev/bcache0 设备现在将存在。 键入 exit 并继续启动。 您可能需要注销缓存设备并再次运行 make-bcache。 对 /dev/bcache0 执行 fsck 也是明智之举。 请参阅 bcache 文档

警告: 仅当以上两个选项均不起作用时才使缓存无效。

/sys/fs/bcache/ 不存在

您启动的内核未启用 bcache,或者您未加载 bcache 模块

尝试附加设备时出现 write error: Invalid argument,原因是块参数不匹配

当尝试附加设备时出现 bash: echo: write error: Invalid argument,并且实际错误通过 dmesg 显示

bcache: bch_cached_dev_attach() Couldn't attach sdc: block size less than set's block size

发生这种情况是因为 --block 4k 参数未在任一设备上设置,并且默认值可能不匹配。

在一个命令中同时创建后端设备和缓存设备会自动解决此问题,但是当使用单独的命令时,有时需要在两个设备上手动设置块大小参数。

设备或资源忙

当设备用作 bcache 后端设备时,无法对其进行格式化或分区

# make-bcache -C /dev/sdb1
Can't open dev /dev/sdb1: Device or resource busy
# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): q

要解决此问题,请首先运行此命令以确认磁盘实际上用作 bcache 后端设备

# bcache-super-show /dev/sdb1
sb.magic		ok
sb.first_sector		8 [match]
sb.csum			A3D2B8610F6C5E35 [match]
sb.version		1 [backing device]

dev.label		(empty)
dev.uuid		5a868788-65a2-4564-b4b7-c1817d0b6080
dev.sectors_per_block	1
dev.sectors_per_bucket	1024
dev.data.first_sector	16
dev.data.cache_mode	1 [writeback]
dev.data.cache_state	2 [dirty]

cset.uuid		42dcb651-6b53-4b65-bc49-9b1ca0acc5b1

然后停止后端设备。 这也将删除相应的 /dev/bcache 设备。

# echo 1 > /sys/class/block/sdb1/bcache/stop
# dmesg
[ 3171.263577] bcache: bcache_device_free() bcache0 stopped

现在可以对设备进行分区

# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): q

当 fdisk 退出时,内核会再次扫描驱动器,注意到它是 bcache 后端设备,并将驱动器用作后端设备。

# dmesg
[ 3190.643270]  sdb: sdb1
[ 3190.833029] bcache: register_bdev() registered backing device sdb1

这将在 /sys/class/block/sdb1/ 下创建目录 bcache

# ls /sys/class/block/sdb1/
alignment_offset  bcache  dev  discard_alignment  holders  inflight  partition	power  ro  size  start	stat  subsystem  uevent

另请参阅