如何在 Linux 中拦截并缓存所有磁盘写入?

如何在 Linux 中拦截并缓存所有磁盘写入?

我犯了一个愚蠢的错误,在摆弄 LVM RAID 设置之前没有进行备份。

我尝试使用 LVM 将 RAID 5 升级到 RAID 6,但我想有些事情就是没有正常工作。我在 LVM RAID 元数据范围中找到了配置备份(当我找到它时,我真的很绝望;我实际上并不认为我会在那里找到任何有用的东西)。

我的想法是使用这些配置备份应用到 LVM vgcfgrestore,但是我想避免对所有磁盘进行写入操作,以防出现问题(即,使用错误配置进行同步/重新扫描/奇偶校验更新可能会覆盖我认为仍然存在的实际数据)。

我非常熟悉使用 OverlayFS 在文件系统级别执行此操作,但我在这里使用块设备,因此不熟悉。我一直在做一些研究,但我发现的所有内容似乎都不太适合这种情况。

  • dm-snapshot将原始数据复制到快照卷(位于 RAM 中)中,因此在发生电源故障或出现其他情况时我真的不想冒险。
  • dm-writecache似乎是个不错的选择,但似乎无法完全阻止写回(也许可以使用非常高的 autocommit_time,但我仍然担心 RAM 受限的 autocommit_blocks)。即便如此,我还是不确定什么可以发送 FLUSH 消息,但如果确实发生这种情况,那将是灾难性的。

有什么办法可以:

  1. 无限期地延迟对特定(或所有)块设备的所有写入,或者
  2. 将所有写入缓存到单独的块设备上

答案1

  1. 关闭系统电源
  2. 购买取证磁盘控制器,又称硬件写阻止设备
  3. 使用取证磁盘控制器对所有驱动器进行 1:1 复制
  4. 尝试恢复数据时处理副本
  5. 进行备份!

答案2

我设法获取了我的数据,但这并非一帆风顺——其中最主要的是驱动器上的所有数据(LVM 和 RAID 元数据除外)都是加密的,因此在尝试之前我无法手动验证我的 RAID 配置。

我使用 手动重建了 RAID 元数据中某个配置中描述的 RAID dmsetup。当我进行最后的 RAID 组装时,我使用了如下命令:

printf "%s\n" "0 23439925248 raid raid6_n_6 4 128 nosync region_size 16384 5 254:0 254:5 254:1 254:6 254:2 254:7 254:3 254:8 254:4  254:9" | dmsetup create RAID_Data

根据 dm-raid 设备的内核文档,这是完全有效的。但是,RAID6 和选项存在一个特定问题nosync,导致无法创建 raid6_n_6 设备,并留下以下 dmesg 错误:

device-mapper: table: 254:10: raid: Invalid flags combination

显然,nosync 不适用于 RAID6。

我的解决方案是:

  1. 使用以下方法为我的各个 LVM PV 设置只读循环设备:losetup -r [loop_dev] [PV_device]
  2. 用于dmsetup create使用只读循环设备重新创建 rmeta 和 rimage 设备。
  3. 创建我的最终 dm-raid 设备,删除选项nosync而不必担心同步破坏数据(因为 dm-raid 设备建立在引用只读循环设备而不是实际磁盘的 dm 设备上)。

我真的很高兴我在转换 RAID 时非常细心,否则我可能根本无法恢复数据。

对于以后偶然发现这一点的任何人:LVM 配置文件中的 region_size 和 stripe_size 是 dmsetup 的直接参数(即,它是 dm 块数,而不是 LVM 范围数)。

编辑:我最初在问题中没有明确说明导致我遇到的问题的事件。导致此问题的命令是从 raid6_n_6 转换为条带卷,这本身应该是安全的。我运行的命令是lvconvert --type striped --stripes 1 vg/lv。LVM 应该不是可能已经允许这种情况发生,但是它确实发生了。

无论如何,转换都是即时的,不需要清理。因此,我确信我的数据仍然可用,只是与卷断开连接。由于卷已转换为条带卷,因此实时系统能够自动安装和激活 LV,而不会因自动清理而导致数据丢失。当然,由于缺少块,我无法在存储所有数据的 LV 内安装加密卷(这也是我第一次发现可能存在问题)。

从实时系统中,我在 lvm.conf 中设置了一个过滤器来过滤掉真正的块设备,并将这些设备映射到只读循环设备以确保安全。

相关内容