職場では、Oracle VM環境の一部としてスパースファイルをゲストディスクイメージとして使用します。同僚にいくつかの質問をした後(現在答えられている)、希少ファイルに関するより多くの質問と、おそらくより一般的なinode構造に関する質問が残っていました。 stat(2) と statfs(2)(FreeBSD(上)) を読んでみると、次のような印象を受けることができます。 Cをもっと知ると分かりやすくなりますが、残念ながらCについての知識はせいぜい微妙です。
私はこれのいくつかがファイルシステムの種類によって異なることを知っています。私はFreeBSD / Solarisとext4のUFSに最も興味があります。 ZFSがあれば、それほど良いことはありません。しかし、私は期待を捨てません。 :)
私は定期的にSolaris 10、FreeBSD 10.3、CentOS 6.7を使用しています。ここのコマンドはCentOS 6.7 VMで実行されますが、FreeBSDと相互参照されています。可能であれば、POSIXの観点から理解したいと思います。可能でない場合は、LinuxよりFreeBSDを好みます。
次のコマンドセットを検討してください。
printf "BIL" > /tmp/BIL
dd of=/tmp/sparse bs=1 count=0 seek=10
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=10
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=17
dd of=/tmp/sparse bs=1 count=0 seek=30
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=30
ファイルに/tmp/BIL
含める必要があるもの(16進数)なので、ファイルを見ると、ファイル4942 004c
全体で次の組み合わせのいくつかを見ることができます。hexdump
/tmp/sparse
%>hexdump sparse
0000000 0000 4942 004c 0000 0000 4942 004c 0000
0000010 4200 4c49 0000 0000 0000 0000 0000 4942
0000020 004c
0000021
%>cat sparse
BILBILBILBIL%
1. 「BIL」が2番目に表示された場合、順序が間違っているのはなぜですか?その4200 4c49
代わりに4942 004c
?これはdd
作成された3番目のコマンドです。
2.他のツールはcat
正しい順序で印刷する方法をどのように知っていますか?
以下を使用して、使用されたls
スペースと割り当てられたブロックを確認できます。
%>ls -ls /tmp/sparse
8.0K -rw-r--r--. 1 bil bil 33 May 26 14:17 /tmp/sparse
主張されたサイズは33バイトですが、割り当てられたサイズは8KB(ファイルシステムブロックサイズは4K)であることがわかります。
3.このようなプログラムは、いわゆるサイズls
と割り当てられたサイズをどのように区別しますか?
inodeに格納されている「いわゆる」数字は直接ブロックと間接ブロックを巡回して計算されますが、割り当てられたサイズは直接ブロックと間接ブロックを巡回することによって計算されます。巡回が正確ではないので、これは正確ではありません。計算を実行すると時間がかかり、非常にls
大きなファイルでも高速戻りなどのツールが必要です。
4. inode 情報を照会するためにどのツールを使用できますか。
わかりましたがstat
、インデックスノードのすべてのフィールドの値が出力されていないようです。
5. 直接ブロックと間接ブロックを巡回できるツールはありますか?
データがどのように保存されるかをよりよく理解するために、ディスクのすべてのアドレスとその内容を調べることは興味深いでしょう。
上記の他のコマンドの後に次のコマンドを実行すると、ファイルが/tmp/sparse
切り捨てられます。
%>dd of=/tmp/sparse bs=1 count=0 seek=5
%>hexdump sparse
0000000 0000 4942 004c
0000005
6.dd
ファイルが切り捨てられ、dd
他のツールがファイルの途中に書き込めるのはなぜですか。
最後に、スパースファイルはスペースを事前に割り当てる良いアイデアのように見えますが、コマンドがファイルを切り捨てたりランダムに増やしたりしないというファイルシステムやオペレーティングシステムレベルの保証はないようです。
7. スパースファイルが縮小/増加するのを防ぐメカニズムはありますか?そうでなければ、スパースファイルはなぜ便利ですか?
上記の各問題は別々の問題かもしれませんが、すべてが基本的な理解に関連しているため、分析することはできません。
答え1
いくつかの簡単な答え:まず、スパースファイルを生成しません。次の追加コマンドを試してください。
dd if=/tmp/BIL of=/tmp/sparse seek=1000
ls -ls /tmp/sparse
サイズは512003バイトですが、8ブロックしか占有されていません。 NULLバイトは、ファイルシステムでまれになるようにブロック全体を占有し、ブロック境界にある必要があります。
2番目に現れる「BIL」 この順序が間違っているのはなぜですか?
なぜなら、リトルエンディアンシステムを使用していて、出力を短い形式で書いているからです。猫のようなバイトを使用してください。
猫や他のツールは正しい順序で印刷する方法をどのように知っていますか?
バイト単位で動作します。
lsなどのプログラムは、いわゆるサイズと割り当てられたサイズをどのように識別しますか?
ls
そして、stat(2)
2つの値を返すシステムコールを使用して、次のように進みます。st_size; /* total size, in bytes */ blkcnt_t st_blocks; /* number of 512B blocks allocated */
inode情報を照会するためにどのツールを使用できますか?
統計は良いです。
直接ブロックと間接ブロックを繰り返すツールはありますか?
hdparm --fibmap
ext2/3/4では、次のファイル名を使用できます。$ sudo hdparm --fibmap ~/sparse filesystem blocksize 4096, begins at LBA 25167872; assuming 512 byte sectors. byte_offset begin_LBA end_LBA sectors 512000 226080744 226080751 8
以下も使用できます
debugfs
。$ sudo debugfs /dev/sda3 debugfs: stat <1040667> Inode: 1040667 Type: regular Mode: 0644 Flags: 0x0 Generation: 1161905167 Version: 0x00000000 User: 127 Group: 500 Size: 335360 File ACL: 0 Directory ACL: 0 Links: 1 Blockcount: 664 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x4dd61e6c -- Fri May 20 09:55:24 2011 atime: 0x4dd61e29 -- Fri May 20 09:54:17 2011 mtime: 0x4dd61e6c -- Fri May 20 09:55:24 2011 Size of extra inode fields: 4 BLOCKS: (0-11):4182714-4182725, (IND):4182726, (12-81):4182727-4182796 TOTAL: 83
ddが私のファイルを切り取り、ddや他のツールがファイルの途中に書き込むことができるのはなぜですか?
はい、
dd
中央まで使えばいいです。に追加してくださいconv=notrunc
。スパースファイルの縮小や拡大を防ぐメカニズムはありますか?そうでなければ、スパースファイルはなぜ便利ですか?
習慣。スペースをあまり占めないからです。
ファイルのスパースはプログラムに完全に透明でなければなりません。これは、時々プログラムがファイルを更新するときにスパース性を失う可能性があることを意味します。
一部のコピーユーティリティには、スパース性を維持するオプションがあります(例tar --sparse
:)rsync --sparse
。
cp --sparse=always
を使用して、ファイル内で適切にソートされたゼロブロックをスパース空間に明示的に変換することができますcp --sparse=never
。
答え2
Linuxでファイルレイアウトをダンプするためのより良いツールは、ソフトウェアパッケージfilefrag
に含まれるユーティリティですe2fsprogs
。これにより、ファイルのすべての範囲が効率的かつ簡潔にダンプされます。
$ dd of=/var/tmp/sparse if=/dev/zero count=1
$ dd of=/var/tmp/sparse if=/dev/zero seek=1000 count=1
$ filefrag -v /var/tmp/sparse
Filesystem type is: ef53
File size of /var/tmp/sparse is 512512 (126 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 3441408.. 3441408: 1:
1: 125.. 125: 3441533.. 3441533: 1: 3441409: last,eof
/var/tmp/sparse: 2 extents found
FIEMAP ioctlは最も一般的なLinuxファイルシステム(ext4、XFS、Btrfsなど)で動作しますが、まだZFSでは動作していません(開発中ですが)。