読み取るだけのファイルやディレクトリを圧縮しつつ、無圧縮時と同様に扱う(概要と準備)
複数のファイルやディレクトリを圧縮すると、その中にあるデータにアクセスするためには、一度それをどこかに展開する必要のある場合が多い*1。
もし、圧縮したいデータが読み取りしかしていないものであれば、読み取り専用の圧縮ファイルシステムにデータを圧縮し、それをマウントするという形をとることで、(多少手間はかかるが)ディスク領域を節約しつつ、圧縮前と同じ感覚で中のデータを開くことができる。
圧縮の対象について
まず、圧縮の基本として、圧縮済みファイル形式(GIF,JPEG,PNGなどの画像、MP3,Vorbis,FLAC,TTA,WMAなどのオーディオ、MPEG,DivX,Xvid,WMVなどのビデオ、などと、挙げていくときりがない)は、それ以上圧縮をかけてもほとんど縮まない。圧縮ファイル(7z,bzip2,gzip,zipなど)も同様だが、圧縮ファイルシステムに圧縮ファイルを入れる意味はあまりない気がする。
これを踏まえた上で、内容を上書きすることのないデータを圧縮の対象とする。以下は有効となりそうな例。
- アプリケーションの実行ファイル。OpenOffice.orgの場合、かなりのディスク容量を食うが、圧縮が結構効くので、全体を圧縮すると、かなりのディスク容量が節約できる。しかし、その他多くの/usr/bin/以下の実行ファイルなどに対しては、運用上、圧縮ファイルシステムを使うことができない。
- テキストデータ。データの性質上、縮みやすいが、編集して上書きすることのないものに限られる。また、bzip2圧縮したテキストファイルは、アプリケーションが読み込み時に展開し、保存時に圧縮を自動的に行ってくれるもの(例: Emacs 22)もあり、テキスト圧縮に読み込み専用ファイルシステムが必ずしもふさわしいとは、一概には言えない。ソフトウェアが吐き出す記録(ログ)ファイルをまとめて圧縮するという使い方は有効と思われる
- CDのイメージファイル。元々のサイズが大きく、節約できる容量も大きい。注意点として、中に圧縮済みデータがある場合はあまり縮まない。特に、GNU/LinuxのLiveCDは、既にcloop*2やSquashfsといった読み取り専用ファイルシステムで圧縮された状態でCDの容量いっぱいになっていて、圧縮の余地がほとんどないため、効果が薄い
- 特殊なオーディオ形式。タグ情報の編集などを後から行うことはできないが、ほとんどの場合は聴くために読み出すだけなのでメリットがあり、形式によっては結構縮むものもある
- 画像や音声などのうち、無圧縮の状態で保管したいがディスク容量は節約したいとき。ただし、音声データの場合、TTA形式にエンコードすると短時間でバランスのよい可逆圧縮ができるので、無圧縮WAVで保管したい理由がなければそちらのほうがよいかも
読み取り専用圧縮ファイルシステムの選択
色々な種類の読み取り専用圧縮ファイルシステムが存在するが、以下の2つを取り上げる。軽さを取るならSquashfs、容量を取るならCromfsと使い分けるのも手。
Squashfs: http://squashfs.sourceforge.net/
圧縮率と速度のバランスがよく、おすすめ。
- 高速に動作
- 安定して動作している実績がある
- そこそこの圧縮率(zlibのdeflateで圧縮、inflateで展開)*3
- カーネルドライバでアクセスするが、kernel.orgがリリースする、パッチの適用されていない状態のカーネル(「Vanillaカーネル」や「素のカーネル」とも呼ばれる)のソースツリーには、バージョン2.6.22の時点では含まれていないため、ソースツリーにパッチを当ててカーネルをビルドする必要がある*4
(2009/3/25)Squashfsはバージョン2.6.29のカーネルからは標準で含まれるようになっている。そのため、独自にパッチを当てたりする必要はない。ただ、それまでのバージョンでもディストリのカーネルを使用している場合はディストリがパッケージを用意していたりすることが多かったので、ユーザにはあまり影響はないかもしれない。
Cromfs: http://bisqwit.iki.fi/source/cromfs.html
速度より圧縮率優先のケースにおいて有用。スペックの低いマシンでは厳しいかも(特にメモリ)。
カーネルが標準でサポートしている「Cramfs」とは別物。
DebianとUbuntuのディストリ付属カーネルでSquashfsを使う
Debian lenny(2007年8月末時点)では、
のようなパッケージ名で、ディストリ付属カーネルに向けた、Squashfsのコンパイル済みカーネルモジュールが提供されているので、CPUアーキテクチャに合ったパッケージをインストールする。
Ubuntu feisty(7.04)では、「squashfs-source」というパッケージをインストールすることで、/usr/src/squashfs.tar.bz2というソースファイルが置かれるので、これを展開してインストールしようとしたのだが失敗。
$ cd /tmp/ $ tar jxf /usr/src/squashfs.tar.bz2 $ cd modules/squashfs/ $ make make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd`/linux-2.6 CONFIG_SQUASHFS=m \ CC="gcc" modules make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' に入ります CC [M] /tmp/modules/squashfs/linux-2.6/inode.o /tmp/modules/squashfs/linux-2.6/inode.c: In function ‘squashfs_iget’: /tmp/modules/squashfs/linux-2.6/inode.c:607: error: ‘struct inode’ has no member named ‘i_blksize’ /tmp/modules/squashfs/linux-2.6/inode.c:660: error: ‘struct inode’ has no member named ‘i_blksize’ /tmp/modules/squashfs/linux-2.6/inode.c: トップレベル: /tmp/modules/squashfs/linux-2.6/inode.c:2103: 警告: ‘kmem_cache_t’ is deprecated /tmp/modules/squashfs/linux-2.6/inode.c: In function ‘squashfs_alloc_inode’: /tmp/modules/squashfs/linux-2.6/inode.c:2109: error: ‘SLAB_KERNEL’ undeclared (first use in this function) /tmp/modules/squashfs/linux-2.6/inode.c:2109: error: (Each undeclared identifier is reported only once /tmp/modules/squashfs/linux-2.6/inode.c:2109: error: for each function it appears in.) /tmp/modules/squashfs/linux-2.6/inode.c: トップレベル: /tmp/modules/squashfs/linux-2.6/inode.c:2122: 警告: ‘kmem_cache_t’ is deprecated /tmp/modules/squashfs/linux-2.6/inode.c: In function ‘destroy_inodecache’: /tmp/modules/squashfs/linux-2.6/inode.c:2146: error: void の値が本来の意味通りに無視されませんでした make[2]: *** [/tmp/modules/squashfs/linux-2.6/inode.o] エラー 1 make[1]: *** [_module_/tmp/modules/squashfs/linux-2.6] エラー 2 make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' から出ます make: *** [modules] エラー 2
これは本家から最新のパッケージ(squashfs3.2-r2.tar.gz)を落としてLinux 2.6.20用のパッチの中のファイルで置き換えることで解決。Ubuntuのパッケージ側に問題があるようだ(2.6.20以外向けのソースの可能性がある)。
$ cd /tmp/ $ tar jxf /usr/src/squashfs.tar.bz2 $ cd modules/squashfs/linux-2.6/ $ rm * -f $ patch -f < [squashfs3.2-r2ディレクトリの場所]/kernel-patches/linux-2.6.20/squashfs3.2-patch >/dev/null $ cd ../ $ make make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd`/linux-2.6 CONFIG_SQUASHFS=m \ CC="gcc" modules make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' に入ります CC [M] /tmp/modules/squashfs/linux-2.6/inode.o CC [M] /tmp/modules/squashfs/linux-2.6/squashfs2_0.o LD [M] /tmp/modules/squashfs/linux-2.6/squashfs.o Building modules, stage 2. MODPOST 1 modules CC /tmp/modules/squashfs/linux-2.6/squashfs.mod.o LD [M] /tmp/modules/squashfs/linux-2.6/squashfs.ko make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' から出ます $ sudo make install make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd`/linux-2.6 CONFIG_SQUASHFS=m \ CC="gcc" modules make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' に入ります Building modules, stage 2. MODPOST 1 modules make[1]: ディレクトリ `/usr/src/linux-headers-2.6.20-16-generic' から出ます install -d /lib/modules/`uname -r`/kernel/fs/squashfs install -m 644 -c `pwd`/linux-2.6/squashfs.ko /lib/modules/`uname -r`/kernel/fs/squashfs /sbin/depmod -a
Squashfsのカーネルパッチについて
http://sourceforge.net/project/showfiles.php?group_id=63835
からダウンロードできるソースを展開すると、カーネルのバージョンごとのディレクトリがあり、その中のパッチ(*.patch)ファイルを適用する。Squashfs 3.2-r2では、kernel-patches/linux-[バージョン]/ディレクトリの中にsquashfs3.2-patchがある。3.2-r2の中には、Linux 2.6.21と2.6.22のディレクトリが無いが、パッチは正常に適用される。
パッチ当ては、カーネルのソースツリーの一番上の階層(通常/usr/src/linux/)で行う。
$ ls -F COPYING MAINTAINERS arch/ fs/ kernel/ scripts/ CREDITS Makefile block/ include/ lib/ security/ Documentation/ README crypto/ init/ mm/ sound/ Kbuild REPORTING-BUGS drivers/ ipc/ net/ usr/
下の例では、Linux 2.6.22のソースツリーに対して2.6.20向けのパッチを適用している。
$ head -n 3 Makefile VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 22
ここから適用作業。「Hunk #1 succeeded」と出ているのは、適用先の行番号が少しずれているだけで、適用自体に問題はない。
$ sudo patch -p1 < [squashfs3.2-r2ディレクトリの場所]/kernel-patches/linux-2.6.20/squashfs3.2-patch patching file fs/Kconfig Hunk #1 succeeded at 1367 (offset -37 lines). patching file fs/Makefile Hunk #1 succeeded at 72 (offset 4 lines). patching file fs/squashfs/inode.c patching file fs/squashfs/Makefile patching file fs/squashfs/squashfs2_0.c patching file fs/squashfs/squashfs.h patching file include/linux/squashfs_fs.h patching file include/linux/squashfs_fs_i.h patching file include/linux/squashfs_fs_sb.h patching file init/do_mounts_rd.c
カーネル手動ビルド時の設定
カーネルのSquashfsサポートを有効にする
Squashfsのパッチが当たっている状態で、これを有効にするには下のように設定する。いずれの項目も、組み込み(*)かモジュール(M)のどちらかを選べる。
Device Drivers ---> Block devices ---> <*> Loopback device support [CONFIG_BLK_DEV_LOOP] File systems ---> Miscellaneous filesystems ---> <*> SquashFS 3.2 - Squashed file system support [CONFIG_SQUASHFS]
Cromfsのインストール
http://bisqwit.iki.fi/source/cromfs.html#download
から最新の.tar.bz2ファイルをダウンロードする。もし、手元に最新の1つ前のバージョンのソースがある場合、差分(patch-cromfs-[最新の1つ前のバージョン]-[最新バージョン].bz2)も使える。
要件として、FUSEのバージョン2.5.2以降が必要。
インストールは、一般ユーザ権限で行えるようになっていて、install/ディレクトリに実行ファイルとドキュメントが入った状態になる。
$ tar jxf cromfs-1.5.3.1.tar.bz2 $ cd cromfs-1.5.3.1/ $ ./configure $ make $ make install (中略) ***************************************** The 'install' directory was prepared. Copy the contents to the locations you see fit. *****************************************
中身は以下のとおり。
$ find install/ install/ install/docs install/docs/size_demo.txt install/docs/WriteAccess.txt install/docs/ImplementationGuide.txt install/docs/BlockIndexing.txt install/docs/ChangeLog install/docs/README.html install/docs/FORMAT install/progs install/progs/unmkcromfs install/progs/mkcromfs install/progs/cvcromfs install/progs/cromfs-driver-static install/progs/cromfs-driver
install/progs/以下の実行ファイルをホームディレクトリの中(例: ${HOME}/bin/)にコピーするなどして使用する。configureスクリプトに--prefixオプションを付けたりしても意味はない。
関連記事: