将块设备挂载为常规文件

将块设备挂载为常规文件

前言

假设我在机器 A 上有一个 1TB 的加密分区,其中包含十几个用户的主目录,我们称这个分区为sda2。我想每天备份远程计算机 B 上的该分区。为了保持安全和简单,B 上的备份必须是 的精确映像副本sda2

sda2我知道我可以使用命令创建本地映像dd,甚至可以通过以下方式将其传送到 B ssh

$ dd if=/dev/sda2 | ssh B dd of=/backups/A.sda2.image

这种方法的问题在于分区的大小。 1TB 的数据不容易通过网络,这限制了备份操作的频率——实际上少于每月一次。此时就需要一个增量备份工具。

rsync在我看来,就是解决之前困难的办法。但是,当我尝试测试它时,我失败了,因为rsync将其/dev/sda2 视为特殊文件和命令:

$ rsync /dev/sda2 B:/backups/A.sda2.image

没有做我想做的事。

问题

有没有办法欺骗rsync处理/dev/sda2常规文件?

笔记

我不是问是否有一个rsync选项可以做到这一点(如果有这样一个选项那就太好了,但这只是故事的一半)我想知道是否有类似命令mount或系统调用之类的东西可以允许例如,我创建一个/mnt/sda2.live_image包含 的原始内容的常规文件/dev/sda2,以便其他应用程序可以通过 直接读取或sda2写入sda2.live_image

任何帮助深表感谢。

答案1

您可以修补直通_fhlibfuse 演示文件系统如下:

diff --git a/example/passthrough_fh.c b/example/passthrough_fh.c
index 13eb41e..146cb03 100644
--- a/example/passthrough_fh.c
+++ b/example/passthrough_fh.c
@@ -72,6 +72,21 @@ static void *xmp_init(struct fuse_conn_info *conn,
    return NULL;
 }

+
+static void b2r(int devfd, struct stat *stbuf)
+{
+   off_t disk_size;
+
+   disk_size = lseek(devfd, 0, SEEK_END);
+   if (disk_size == -1)
+       return;
+
+   stbuf->st_size = disk_size;
+   stbuf->st_blocks = disk_size / stbuf->st_blksize;
+   stbuf->st_mode &= ~S_IFBLK;
+   stbuf->st_mode |= S_IFREG;
+}
+
 static int xmp_getattr(const char *path, struct stat *stbuf,
            struct fuse_file_info *fi)
 {
@@ -85,6 +100,16 @@ static int xmp_getattr(const char *path, struct stat *stbuf,
        res = lstat(path, stbuf);
    if (res == -1)
        return -errno;
+   if (S_ISBLK(stbuf->st_mode)) {
+       int fd;
+       if (fi)
+           fd = fi->fh;
+       else
+           fd = open(path, O_RDONLY);
+       b2r(fd, stbuf);
+       if (!fi)
+           close(fd);
+   }

    return 0;
 }

如果将其安装为 root,它将向您提供文件系统的镜像,其中块设备显示为常规文件。仅传递-omodules=subdir,subdir=/dev到镜像 /dev。

(我在我的双启动 Mac/Linux 机器上使用此补丁的一个变体,以便能够将我的 Linux 安装作为 OS X 中的 Xhyve VM 启动,因为 Xhyve 拒绝使用块设备。)

答案2

正如评论中所解释的,基于块设备的备份通常是一个错误的想法。

在非加密设备上,通常会使用以下步骤来完成此操作:

  1. 用零 ( dd if=/dev/zero of=<mountpoint>/tmp_zero_file bs=1M) 填充空白空间,以便以更好的比率压缩可用空间。
  2. 然后dd if=<your block device> |gzip -9 | ssh backup_host "cat > backup.gz"
  3. 然后rm <mountpoint>/tmp_zero_file

这里的问题是,由于您的磁盘已加密,因此将 0 写入文件惯于由于加密层的原因,导致块归零。

对于您的用例,我强烈建议使用表里不一这是一个基于rsync的备份工具,实现加密和增量备份。

答案3

只要你查看整个分区,你就必须整个阅读才能发现发生了什么变化。事实上你必须阅读新版本和旧版本才能找到变化,所以你最好直接把整个东西复制过来。使用千兆位以太网和良好的磁盘,您可以获得 100MB/s,因此您的 TB 将需要 10000 秒或大约 3 小时,因此每晚备份是可行的。 OTOH,如果目标是 SSD,你会很快磨损它。

注意,你做的不是备份而是镜像。如果用户在一次镜像发生后才发现错误删除文件,这并不能真正帮助他们。

相关内容