過度分配的稀疏文件沒有寫入失敗
我一直在使用稀疏文件,以便在 Windows samba 上複製 Linux fs 權限,從這里安裝一個想法:https ://www.thanassis.space/backup.html 。
雖然在測試稀疏文件時,我發現了一個有趣的問題,其中“完整”的主機驅動器不會報告為應用程序的寫入失敗。相反,當主機驅動器填滿時,寫入會繼續並成功完成,即使驅動器已滿。
為了測試這一點,我有以下設置。
[root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 944M 7.1G 12% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 49M 1.7G 3% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 33M 4.0G 1% /mnt tmpfs 354M 0 354M 0% /run/user/0
我已經安裝了一個 4G 分區
/mnt
,我將在該分區上創建一個 10G 稀疏文件。[root@ip-172-31-61-147 ~]# dd of=/mnt/file bs=1G count=0 seek=10 0+0 records in 0+0 records out 0 bytes (0 B) copied, 3.0097e-05 s, 0.0 kB/s
該文件已正確創建並且不佔用分區上的實際空間,但似乎是一個 10G 文件。
[root@ip-172-31-61-147 ~]# ls -lh /mnt/ total 0 -rw-r--r--. 1 root root 10G Aug 28 21:10 file [root@ip-172-31-61-147 ~]# du -h /mnt/ 0 /mnt/
我在空間中分配一個文件系統並掛載它(通過 losttup 驗證)。
[root@ip-172-31-61-147 ~]# mkfs.xfs /mnt/file meta-data=/mnt/file isize=512 agcount=4, agsize=655360 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=2621440, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 [root@ip-172-31-61-147 ~]# mount /mnt/file /srv/ [root@ip-172-31-61-147 ~]# losetup -j /mnt/file /dev/loop0: [51729]:67 (/mnt/file) [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 945M 7.1G 12% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 49M 1.7G 3% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 43M 4.0G 2% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 33M 10G 1% /srv [root@ip-172-31-61-147 ~]#
在這個掛載點上,我可以正常寫入文件,表明它工作正常。
[root@ip-172-31-61-147 ~]# dd if=/dev/zero of=/srv/init_file bs=1GiB count=1 1+0 records in 1+0 records out 1073741824 bytes (1.1 GB) copied, 8.22444 s, 131 MB/s [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 945M 7.1G 12% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 49M 1.7G 3% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 1.1G 3.0G 27% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 1.1G 9.0G 11% /srv [root@ip-172-31-61-147 ~]# ls -lh /srv/ total 1.0G -rw-r--r--. 1 root root 1.0G Aug 28 21:19 init_file [root@ip-172-31-61-147 ~]# [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 945M 7.1G 12% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 49M 1.7G 3% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 1.1G 3.0G 27% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 1.1G 9.0G 11% /srv
現在,當我嘗試創建一個應該超出主機驅動器的文件時,它也會正確寫入並且不會報告錯誤。
[root@ip-172-31-61-147 ~]# dd if=/dev/zero of=/srv/too_large_a_file bs=1GiB count=4 4+0 records in 4+0 records out 4294967296 bytes (4.3 GB) copied, 49.9905 s, 85.9 MB/s [root@ip-172-31-61-147 ~]# echo $? 0
相關數據:
[root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 949M 7.1G 12% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 49M 1.7G 3% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 5.1G 5.0G 51% /srv [root@ip-172-31-61-147 ~]# du -h /srv/ 5.0G /srv/ [root@ip-172-31-61-147 ~]# du -h /srv/* 1.0G /srv/init_file 4.0G /srv/too_large_a_file [root@ip-172-31-61-147 ~]# ls -lh /srv/ total 5.0G -rw-r--r--. 1 root root 1.0G Aug 28 21:19 init_file -rw-r--r--. 1 root root 4.0G Aug 28 21:24 too_large_a_file [root@ip-172-31-61-147 ~]#
我嘗試使用其他實用程序(例如
rsync
和)來複製這種行為cp
。也不會報告錯誤,而是靜默失敗。使用 cp:
[root@ip-172-31-61-147 ~]# cp -v too_large_a_file /srv/ ‘too_large_a_file’ -> ‘/srv/too_large_a_file’ [root@ip-172-31-61-147 ~]# echo $? 0 [root@ip-172-31-61-147 ~]# ls -lhtr /srv/ total 5.0G -rw-r--r--. 1 root root 5.0G Aug 28 21:31 too_large_a_file [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 6.0G 2.1G 75% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 57M 1.7G 4% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 5.1G 5.0G 51% /srv
使用 rsync:
[root@ip-172-31-61-147 ~]# rsync -vvv too_large_a_file /srv/ [sender] make_file(too_large_a_file,*,0) send_file_list done send_files starting server_recv(2) starting pid=16569 received 1 names recv_file_list done get_local_name count=1 /srv/ generator starting pid=16569 delta-transmission disabled for local transfer or --whole-file recv_generator(too_large_a_file,0) send_files(0, too_large_a_file) send_files mapped too_large_a_file of size 5368709120 calling match_sums too_large_a_file too_large_a_file sending file_sum false_alarms=0 hash_hits=0 matches=0 sender finished too_large_a_file send_files phase=1 recv_files(1) starting generate_files phase=1 recv_files(too_large_a_file) got file_sum renaming .too_large_a_file.CwVApY to too_large_a_file recv_files phase=1 generate_files phase=2 send_files phase=2 send files finished total: matches=0 hash_hits=0 false_alarms=0 data=5368709120 recv_files phase=2 generate_files phase=3 recv_files finished generate_files finished sent 5369364558 bytes received 31 bytes 57426359.24 bytes/sec total size is 5368709120 speedup is 1.00 [sender] _exit_cleanup(code=0, file=main.c, line=1052): about to call exit(0) [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 6.0G 2.1G 75% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 73M 1.7G 5% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/0 /dev/loop0 10G 5.1G 5.0G 51% /srv
執行後
md5sum
我更加困惑:[root@ip-172-31-61-147 ~]# md5sum /root/too_large_a_file ec4bcc8776ea04479b786e063a9ace45 /root/too_large_a_file [root@ip-172-31-61-147 ~]# md5sum /srv/too_large_a_file ec4bcc8776ea04479b786e063a9ace45 /srv/too_large_a_file
似乎完整的文件被保留了,雖然我不知道如何。
在研究這個問題時,我發現有人在做同樣的事情但使用加密設置,他們發現了同樣的問題但無法解決它(事實上他們建議將它作為一個新問題打開!):使用 LUKS 按需增長加密卷。
任何幫助都會很棒。
編輯:根據請求核心和系統資訊
[root@ip-172-31-61-147 ~]# uname -a Linux ip-172-31-61-147 3.10.0-514.16.1.el7.x86_64 #1 SMP Wed Apr 12 15:04:24 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux [root@ip-172-31-61-147 ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core)
根據提供的答案,我創建了新文件來測試
/dev/zero
理論。我創建了一個包含所有文件的文件並嘗試複製我的發現並發現它仍然成功。[root@ip-172-31-61-147 ~]# tr '\0' '\377' < /dev/zero | dd bs=1 count=5G of=~/too_large_a_file [root@ip-172-31-61-147 ~]# du -h too_large_a_file 982M too_large_a_file
然後我將該文件的多個副本放在稀疏文件掛載上(例如
cp too_large_a_file /srv/too_large_a_file_1
)我能夠將其中六個文件複製到外部,而沒有一個副本失敗。
[root@ip-172-31-61-147 ~]# ls -lh /srv/ total 4.8G -rw-r--r--. 1 root root 982M Aug 29 00:14 too_large_a_file -rw-r--r--. 1 root root 982M Aug 29 00:26 too_large_a_file_2 -rw-r--r--. 1 root root 982M Aug 29 02:34 too_large_a_file_3 -rw-r--r--. 1 root root 982M Aug 29 02:34 too_large_a_file_4 -rw-r--r--. 1 root root 982M Aug 29 02:35 too_large_a_file_5
驅動器顯然也在這裡最大化。
Filesystem 1K-blocks Used Available Use% Mounted on /dev/xvda1 8377344 1975040 6402304 24% / devtmpfs 1920720 0 1920720 0% /dev tmpfs 1809256 0 1809256 0% /dev/shm tmpfs 1809256 82192 1727064 5% /run tmpfs 1809256 0 1809256 0% /sys/fs/cgroup /dev/xvdb1 4183040 4183020 20 100% /mnt tmpfs 361852 0 361852 0% /run/user/1000 /dev/loop0 10475520 5055864 5419656 49% /srv
所有文件和原始文件的 md5sum 如下。
[root@ip-172-31-61-147 ~]# md5sum too_large_a_file e8154ef97a3eb2bd13aea04b823a4570 too_large_a_file [root@ip-172-31-61-147 ~]# md5sum /srv/* e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file_2 e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file_3 e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file_4 154248d2eeaf5791dfc8199e51daadbc /srv/too_large_a_file_5
我會補充一點,這顯然會影響系統,因為添加第六個文件會使它崩潰。注意:複製完成後系統再次響應。**編輯 2:**添加
du
資訊。[root@ip-172-31-61-147 ~]# du -h /srv/* 982M /srv/too_large_a_file 982M /srv/too_large_a_file_2 982M /srv/too_large_a_file_3 982M /srv/too_large_a_file_4 982M /srv/too_large_a_file_5
**編輯3:**記憶體資訊我通過刪除“超出”緩衝區的文件來測試這一點,然後複製一個並刪除記憶體並查看發生了什麼。
[root@ip-172-31-61-147 ~]# rm /srv/too_large_a_file_5 rm: remove regular file ‘/srv/too_large_a_file_5’? y [root@ip-172-31-61-147 ~]# cp too_large_a_file /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 2.2G 5.9G 28% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 97M 1.7G 6% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/1000 /dev/loop0 10G 4.9G 5.2G 49% /srv [root@ip-172-31-61-147 ~]# free -m && sync && echo 3 > /proc/sys/vm/drop_caches && free -m total used free shared buff/cache available Mem: 3533 93 1210 104 2229 3091 Swap: 0 0 0 total used free shared buff/cache available Mem: 3533 94 3281 104 157 3183 Swap: 0 0 0 [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 2.2G 5.9G 28% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 105M 1.7G 6% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/1000 /dev/loop0 10G 4.9G 5.2G 49% /srv [root@ip-172-31-61-147 ~]# md5sum /srv/too_large_a_file_5 154248d2eeaf5791dfc8199e51daadbc /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# du -ah /srv/ 982M /srv/too_large_a_file 982M /srv/too_large_a_file_2 982M /srv/too_large_a_file_3 982M /srv/too_large_a_file_4 982M /srv/too_large_a_file_5 4.8G /srv/ [root@ip-172-31-61-147 ~]# ls -lh /srv/ total 4.8G -rw-r--r--. 1 root root 982M Aug 29 00:14 too_large_a_file -rw-r--r--. 1 root root 982M Aug 29 00:26 too_large_a_file_2 -rw-r--r--. 1 root root 982M Aug 29 02:34 too_large_a_file_3 -rw-r--r--. 1 root root 982M Aug 29 12:16 too_large_a_file_4 -rw-r--r--. 1 root root 982M Aug 29 12:27 too_large_a_file_5 [root@ip-172-31-61-147 ~]#
**編輯4:**記憶資訊繼續我對我的發現持懷疑態度,我又做了一次測試,這似乎有點啟發性。似乎在轉儲記憶體後文件確實發生了變化,
md5sum
輸出確實更新了。[root@ip-172-31-61-147 ~]# rm /srv/too_large_a_file_5 rm: remove regular file ‘/srv/too_large_a_file_5’? y [root@ip-172-31-61-147 ~]# cp too_large_a_file /srv/too_large_a_file_5 (reverse-i-search)`m': r^C/srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# md5sum /srv/too_large_a_file_5 e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# [root@ip-172-31-61-147 ~]# [root@ip-172-31-61-147 ~]# md5sum /srv/too_large_a_file_5 e8154ef97a3eb2bd13aea04b823a4570 /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# free -m && sync && echo 3 > /proc/sys/vm/drop_caches && free -m total used free shared buff/cache available Mem: 3533 93 298 104 3141 3091 Swap: 0 0 0 total used free shared buff/cache available Mem: 3533 93 3274 112 166 3175 Swap: 0 0 0 [root@ip-172-31-61-147 ~]# md5sum /srv/too_large_a_file_5 154248d2eeaf5791dfc8199e51daadbc /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 2.2G 5.9G 28% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 113M 1.7G 7% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup /dev/xvdb1 4.0G 4.0G 20K 100% /mnt tmpfs 354M 0 354M 0% /run/user/1000 /dev/loop0 10G 4.9G 5.2G 49% /srv
重啟後
[root@ip-172-31-61-147 ~]# mount /mnt/file /srv/ [root@ip-172-31-61-147 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 8.0G 2.2G 5.9G 28% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.8G 0 1.8G 0% /dev/shm tmpfs 1.8G 17M 1.8G 1% /run tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup tmpfs 354M 0 354M 0% /run/user/1000 /dev/xvdb1 4.0G 4.0G 20K 100% /mnt /dev/loop0 10G 4.9G 5.2G 49% /srv [root@ip-172-31-61-147 ~]#
**編輯 5:**同步資訊
似乎以同步方式安裝文件會產生錯誤。
[root@ip-172-31-61-147 ~]# mount -odefaults,sync /mnt/file /srv/ [root@ip-172-31-61-147 ~]# mount sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel) ..snip.. /dev/xvdb1 on /mnt type xfs (rw,relatime,seclabel,attr2,inode64,noquota) /mnt/file on /srv type xfs (rw,relatime,sync,seclabel,wsync,attr2,inode64,noquota) [root@ip-172-31-61-147 ~]# cp too_large_a_file /srv/too_large_a_file_5 [root@ip-172-31-61-147 ~]# cp too_large_a_file /srv/too_large_a_file_5 cp: error writing ‘/srv/too_large_a_file_5’: Input/output error cp: failed to extend ‘/srv/too_large_a_file_5’: Input/output error [root@ip-172-31-61-147 ~]# ls /srv/ too_large_a_file too_large_a_file_2 too_large_a_file_3 too_large_a_file_4 too_large_a_file_5
盒子上是否有足夠的記憶體來完全記憶體文件內容?無論如何,我認為這是一個在核心/文件系統實現中尚未解決的極端情況錯誤。畢竟,這裡有很多層在起作用。
“現在,當我嘗試創建一個應該超出主機驅動器的文件時,它也會正確寫入並且不會報告錯誤。”
[root@ip-172-31-61-147 ~]# dd if=/dev/zero of=/srv/too_large_a_file
是的,它會正確寫入,因為您正在寫入零,這是稀疏文件的內容,除非它被覆蓋到其他內容,因此您在此處所做的操作不會向稀疏文件寫入任何內容。如果你寫的不是零,寫就會失敗。
cp 和 rsync 可能會根據作業系統和核心版本保持稀疏性。