我想做一些类似的事情
mkfs -t btrfs filedrive
mount filedrive /media/fuse
在不指定特定大小的情况下,我希望能够在将文件写入已安装的文件系统时增大文件的大小,并在删除文件时缩小文件的大小。
有什么机制可以做到这一点吗?
我也见过这个问题我知道理论上它可以手动管理,但我的问题与 ecryptfs 无关,而是集中在自动方面。我并不特别关心文件内的文件系统类型。
我还知道现有的系统可以执行类似的操作:特别是 VirtualBox 的动态磁盘。如果有某种方法可以使用它们 - 或类似的东西 - 而无需实际运行虚拟机,我也会对此感到满意。
答案1
事实上,类似的事情已经成为可能
文件系统需要定义最大大小。但由于文件系统即文件可以疏,该大小可以是任意数字,与文件系统文件在底层文件系统上占用的空间没有太大关系。
如果您可以接受为文件系统即文件设置任意最大大小限制(可以远大于底层文件系统的实际大小),那么您现在可以在其上创建一个稀疏文件和一个文件系统:
/tmp# df -h .
Filesystem Size Used Avail Use% Mounted on
<current filesystem> 20G 16G 3.0G 84% /
/tmp# dd if=/dev/null bs=1 seek=1024000000000 of=testdummy
0+0 records in
0+0 records out
0 bytes copied, 0.000159622 s, 0.0 kB/s
/tmp# ll testdummy
-rw-r--r-- 1 root root 1024000000000 Feb 19 08:24 testdummy
/tmp# ll -h testdummy
-rw-r--r-- 1 root root 954G Feb 19 08:24 testdummy
在这里,我创建了一个文件,它看起来比它存储的文件系统大得多......
/tmp# du -k testdummy
0 testdummy
...但到目前为止,它实际上根本不占用任何磁盘空间(除了 inode 和可能其他一些元数据)。
完全有可能losetup
在其上创建一个文件系统并开始使用它。每个实际将数据写入文件的写入操作都会导致文件的空间需求增加。换句话说,虽然报告的文件大小ls -l
始终保持任意巨大的数字,但报告的文件在磁盘上占用的实际空间du
将会增长。
如果您使用挂载选项挂载文件系统作为文件discard
,收缩也可以自动进行:
/tmp# losetup /dev/loop0 testdummy
/tmp# mkfs.ext4 /dev/loop0
/tmp# mount -o discard /dev/loop0 /mnt
/tmp# du -k testdummy
1063940 testdummy
/tmp# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/loop0 938G 77M 890G 1% /mnt
/tmp# cp /boot/initrd.img /mnt
/tmp# du -k testdummy
1093732 testdummy
/tmp# rm /mnt/initrd.img
/tmp# du -k testdummy
1063944 testdummy
自动收缩需要:
1.) filesystem-as-file 的文件系统类型支持discard
mount 选项(以便文件系统驱动程序可以告诉底层系统哪些块可以被释放)
2.) 并且底层文件系统的文件系统类型支持“打孔”,即fallocate(2)
带有选项的系统调用FALLOC_FL_PUNCH_HOLE
(以便底层文件系统可以被告知将文件系统的一些先前分配的块标记为文件再次作为稀疏块)
3.) 并且您使用的是内核版本 3.2 或更高版本,以便循环设备支持为此拥有必要的基础设施。
https://outflux.net/blog/archives/2012/02/15/discard-hole-punching-and-trim/
如果您不介意立即收缩,则可以定期fstrim
在文件系统作为文件上运行,而不是使用discard
挂载选项。如果底层文件系统非常繁忙,避免立即收缩可能有助于最大限度地减少底层文件系统的碎片。
这种方法的问题是,如果底层文件系统已满,则不会得到很好的处理。如果底层文件系统中不再有空间,则文件系统即文件在尝试用实际数据替换稀疏“漏洞”时将开始接收错误,即使文件系统即文件似乎还留有一些未使用的容量。
答案2
不,不会自动支持
创建文件系统是为了处理固定数量的磁盘空间。一些文件系统支持增长,少数支持收缩,但在没有用户干预的情况下不能按需。您提到的问题的答案表明您必须手动调整大小。
当然,可以手动完成的事情也可以自动完成,但是需要内核的支持,如果文件系统已满,它不会报告文件系统已满,而是会扩大文件系统。您还希望在删除文件时自动收缩文件系统,这可能是一个非常耗时的操作,因为您可能必须移动数据,以便文件系统末尾的空间可用。
专门为此任务创建的文件系统可以在增长时在末尾分配块,在收缩时在中间释放块,但似乎没有人想要创建这样的文件系统。当然,您可以自由地自己做。
VirtualBox 的动态磁盘不一样。它们是用固定的最大大小创建的,只是不会立即用掉那么多的磁盘空间。一旦数据写入该块,就会分配该块,并且不会因为该块未使用而缩小。
答案3
使用稀疏文件+循环设备+TRIM作为接受的方式很好,但是我不太相信你的问题不是XY问题:为什么不简单地使用子目录/子树?它会根据需要增长和缩小,您也可以使用mount --bind
NFS 或 NFS 安装在另一个地方;-)
我还知道现有的系统可以执行类似的操作:特别是 VirtualBox 的动态磁盘。如果有某种方法可以使用它们 - 或类似的东西 - 而无需实际运行虚拟机,我也会对此感到满意。
通过qemu-ndb
,您还可以在主持人系统支持的任何磁盘映像qemu
:
# modprobe nbd
# qemu-nbd --discard=unmap -c /dev/nbd1 image.qcow2
# kpartx -a /dev/nbd1
# mount /dev/mapper/nbd1p1 /mount/point
...
# fstrim -v /mount/point
...
# qemu-nbd -d /dev/nbd1
Qemu 的 qcow2 映像不仅可以增大和缩小以容纳数据,还支持快照和“差异”映像。
答案4
看起来对我来说最好的选择是使用truncate
.它会自动扩展。我不确定你是否可以修剪它。
https://superuser.com/questions/1096549/file-based-dynamically-allocated-hard-disk-on-linux
truncate -s 1G /tmp/file.img
du -h /tmp/file.img
#1.0K /tmp/file.img
du -h --apparent-size /tmp/file.img
#10G /tmp/file.img
losetup -f # or use mount to a mountpoint
#/dev/loop12
losetup /dev/loop12 /tmp/file.img
mkfs.ext4 -m0 /dev/loop12