#disk-space #blake3 #deduplication #utility #deduplicate #reflink

app reflicate

通过在相同文件之间创建reflinks来去重数据

4个版本 (2个破坏性更新)

0.3.1 2023年9月24日
0.3.0 2023年8月12日
0.2.0 2023年1月16日
0.1.0 2023年1月8日

#296文件系统

MIT 许可证

18KB
359

Reflicate

通过在相同文件之间创建reflinks来去重数据。

安装

$ cargo install reflicate
$ export PATH=$PATH:~/.cargo/bin

免责声明

这是一个alpha质量的软件。请自由地在您的系统上测试此程序并报告错误。但请记住先备份。

摘要

reflicate [<directories...>] [-d] [-h] [-i <indexfile>] [-p] [-q]  
  
Positional Arguments:
  directories       directories to deduplicate

Options:
  -d, --dryrun      do not make any filesystem changes
  -h, --hardlinks   make hardlinks instead of reflinks
  -i, --indexfile   store computed hashes in indexfile and use them in subsequent runs
  -p, --paranoid    compute sha256 hashes in addition to blake3 hashes
                    and do not trust precomputed hashes from indexfile
  -q, --quiet       be quiet

描述

Reflicate 会扫描指定的目录以查找相同文件并将它们reflink在一起。文件被认为是相同的,当它们具有相同的大小和相同的blake3哈希时。reflinked文件共享相同的磁盘块,因此磁盘空间只占用一次。在编辑文件时,它会将文件复制到不同的块中,因此可以安全地reflink当前具有相同内容但可能将来会不同的文件。

硬链接与reflinks在两个方面有所不同

  • 硬链接几乎由所有posix文件系统支持,而reflinks只被少数文件系统支持,例如XFS、BTRFS、OCFS2。
  • 硬链接共享相同的inode,因此硬链接文件始终一起编辑。

索引文件

Reflicate 在索引文件中存储四个值:文件路径、文件大小、修改时间和blake3哈希。在后续运行中,它只对大小或修改时间不同的文件计算哈希。这意味着当使用索引文件时,程序可以更快地运行。

内部索引文件是CDB(常量数据库)和msgpack的组合。这意味着索引文件将在后续运行中被覆盖,因此如果您在不同的目录中使用reflicate,请使用不同的索引文件。

偏执模式

默认情况下,reflicate 计算并比较blake3哈希,但在偏执模式下也使用sha256哈希。此外,在偏执模式下,总是计算所有哈希,因为可能可以操纵文件修改时间。

Systemd

可以使用Systemd计时器定期运行。为此,您需要运行以下命令

$ mkdir -p ~/.config/systemd/user/
$ cp systemd/* ~/.config/systemd/user/
$ systemctl --user daemon-reload
$ systemctl --user enable reflicate.timer

默认情况下,定期任务每周运行一次,并且reflicate您的家目录。您可以通过编辑reflicate.servicereflicate.timer文件来根据您的需求进行调整。

展示

首先,让我们创建一个XFS文件系统,将其挂载,并创建一个测试目录。

$ dd if=/dev/zero of=test.img bs=1M count=100
$ mkfs.xfs test.img
$ sudo mount -o loop test.img /mnt
$ sudo mkdir /mnt/test
$ sudo chown `id -u` /mnt/test

然后创建两个相同和两个不同的文件。

$ dd if=/dev/zero of=/mnt/test/file1 bs=1M count=10
$ dd if=/dev/zero of=/mnt/test/file2 bs=1M count=10
$ dd if=/dev/zero of=/mnt/test/file3 bs=1M count=12
$ dd if=/dev/zero of=/mnt/test/file4 bs=1M count=15

现在我们可以看到,占用了53 MiB的磁盘空间(包括元数据)。

$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       95M   53M   42M  56% /mnt

让我们reflicate测试目录。

$ reflicate /mnt/test/
/mnt/test/file2 => /mnt/test/file1 [10 MiB]
10 MiB saved

我们看到目前只占用了43 MiB的磁盘空间。

$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       95M   43M   52M  46% /mnt

让我们断开reflink并创建一个与file3内容相同的file2。

$ dd if=/dev/zero of=/mnt/test/file2 bs=1M count=12

$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       95M   55M   40M  59% /mnt

然后再次强复制测试目录。

$ reflicate /mnt/test/
/mnt/test/file3 => /mnt/test/file2 [12 MiB]
12 MiB saved

$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0       95M   43M   52M  46% /mnt

最后,让我们删除测试文件系统。

$ sudo umount /mnt
$ rm test.img

依赖项

~2.7–4MB
~89K SLoC