可以通过稀疏文件使 Lostup 变得高效吗?

可以通过稀疏文件使 Lostup 变得高效吗?

所以我的设置是这样的。

$ truncate -s 1T volume
$ losetup -f --show volume
/dev/loop0
$ mkfs.ext4 /dev/loop0
$ ls -sh volume
1.1G volume
$ mount /dev/loop0 /mnt/loop

现在我有 1.1TB 的卷,正如预期的那样。 ext4 的开销将稀疏文件扩展至 1.1G,但这没关系。现在添加一个文件。

$ dd if=/dev/urandom of=/mnt/loop/file bs=1M count=10240
$ ls -sh volume
12G volume

很好,现在我不想要这个文件了。

$ rm /mnt/loop/file
$ ls -sh volume
12G volume

正如预期的那样,可用空间仍然占用空间,并$ fallocate -d volume释放了 1GB。

我的问题是,如何在不将卷扩展到完整大小的情况下将此处的可用空间清零?$ dd if=/dev/zero会将其扩展至完整大小,并conv=sparse使其在卷内创建一个无用的稀疏文件。

TL;DR:有没有一种方法可以losetup忽略空块对空扇区的写入,同时允许其他所有操作?

答案1

要在不再使用数据块时自动丢弃它们,请使用mount -o discard ...。或者您可以手动运行fstrim

这个功能显然是在 Linux 3.2 中添加到循环设备中的。 https://outflux.net/blog/archives/2012/02/15/discard-hole-punching-and-trim/


一般情况下,mount -o discard不保证有效,因为某些类型的设备在繁忙时被允许忽略丢弃请求。不过,这不会影响稀疏文件的大小。

在这种一般情况下 - 例如,如果您还想向底层物理设备发送丢弃请求 - 最可靠的方法是fstrim定期运行。

答案2

不是使用内置工具的解决方案,但我编写了一个 python 脚本来执行我想要的操作。如果它对任何人有帮助的话,就在这里。仍在寻找内置解决方案(如果有的话)。

#!/usr/bin/python3.6
import os
import time
import sys

if len(sys.argv) != 2:
    print('''Usage: {} <file>

Fills a file/device with zeros, with efficiencies for sparse files.'''.format(sys.argv[0]))
    exit(1)

f = open(sys.argv[1], 'rb+', 0)

bs = 1024*1024 # block size
zb = b'\0'*bs  # a full block of zeros

lasttime = round(time.time())
block = f.read(bs)
while len(block) == bs:

    # IFF a block contains non-zero characters, zero it
    if block != zb:
        f.seek(-bs, os.SEEK_CUR)
        f.write(zb)
    block = f.read(bs)

    # Print the processed bytes every second
    # Could add a MB/s or % completed, but too lazy
    if round(time.time()) != lasttime:
        print(f.tell())
        lasttime = round(time.time())

# Hit EOF, might have missed bytes at the end
# Zero last block unconditionally, too lazy to check if its required
f.seek(-bs, os.SEEK_CUR)
f.write(zb)
f.close()

相关内容