LVM + reiserfs 適用時のスナップショットマウント不具合


はじめに(事の経緯とか)

サーバ稼働中に、ハードディスクの確実なバックアップを取るためには、稼働中のあらゆるプログラムを停止する必要がある。しかしながら、バックアップのたびにシステムを停止するといった運用は、24/7な運用が前提であるインターネットサーバなどには適用できない。例えば、RAIDによる冗長化構成の適用も考えられるが、今回は、ディスク増設時の拡張性を考えて、rsyncによる別ディスクへのコピーによる単純なバックアップでいくことにした(単に同容量のディスクを何本も買うだけの余裕がないだけ、という理由かも:-p) 。
この場合、バックアップ時に対象となる(複写元の)ファイルシステムは、readonlyでマウントする必要があるが、そのためにシステムを再起動するわけにもいかない。そこで、LVMの登場である。LVMとは、Logical Volume Manager のことで、読んで字のごとく、Linuxにおける論理ボリューム管理機能である。LVMを使うと、ファイルシステムに割り当てるディスクボリュームの容量を動的に拡張したり縮小したりできるようになる。(通常、linuxでは、ファイルシステムの容量はマウントする区画の容量に依存するわけだが、LVMだと区画やディスクを跨ったボリュームをファイルシステムに割り当てることができる!)。
LVMの特徴はこれだけにとどまらない。LVM は「スナップショット」というユニークな機能を持っていて、ある決まった時点でのファイルシステムの内容をバックアップすることができる。この興味をそそる機能が、今回のディスクバックアップに極めて有効であることから、さっそく導入することにした。

Vine Linux 2.5 にLVMを導入

LinxでLVMを導入するためには、LVMに対応したカーネルと関連ツールのインストールが必要である。2.4系のカーネルであれば、標準でLVMに対応しているから、LVMをカーネルに組み込むかモジュール化する設定にしてカーネルがmakeされていればOKである。(Vine Linux 2.5では、標準でモジュール化されている。)
関連ツールも必要であるが、残念ながらVine Linuxではrpmパッケージが用意されていないため、http://www.sistina.com/products_lvm_download.htm からtar ballをダウンロードしてmake & installすることになる。
この辺のノウハウは、以下のサイトを参考にするとよい。

なお、LVMをモジュール化して導入する場合は、/etc/modules.confに以下の記述を追加すること。
    alias block-major-58      lvm-mod
    alias char-major-109      lvm-mod

スナップショットがマウントできない(涙)

今回、私は/dev/hda5と/dev/hda7またがった二つの区画(PE:Physical Extent)を、vg01というひとつのボリューム(VG:Volume Group)にまとめ、ここから、lv_var lv_homeという二つの論理ボリューム(LV:Logical Volume)を切り出した。vgdisplayで表示される情報を以下に示す。
--- Volume group ---
VG Name               vg01
VG Access             read/write
VG Status             available/resizable
VG #                  0
MAX LV                256
Cur LV                2
Open LV               2
MAX LV Size           255.99 GB
Max PV                256
Cur PV                2
Act PV                2
VG Size               23.11 GB
PE Size               4 MB
Total PE              5916
Alloc PE / Size       2560 / 10 GB
Free  PE / Size       3356 / 13.11 GB

--- Logical volume ---
LV Name                /dev/vg01/lv_home
VG Name                vg01
LV Write Access        read/write
LV Status              available
LV #                   1
# open                 1
LV Size                5 GB
Current LE             1280
Allocated LE           1280
Allocation             next free
Read ahead sectors     1024
Block device           58:0

--- Logical volume ---
LV Name                /dev/vg01/lv_var
VG Name                vg01
LV Write Access        read/write
LV Status              available
LV #                   2
# open                 1
LV Size                5 GB
Current LE             1280
Allocated LE           1280
Allocation             next free
Read ahead sectors     1024
Block device           58:1


--- Physical volumes ---
PV Name (#)           /dev/hda5 (1)
PV Status             available / allocatable
Total PE / Free PE    2558 / 0

PV Name (#)           /dev/hda7 (2)
PV Status             available / allocatable
Total PE / Free PE    3358 / 3356

上記のlv_varとlv_homeは、それぞれ/var /home をマウントしており、それぞれreiserfsで初期化した。以下は、mount状況(抜粋)である。
/dev/vg01/lv_home on /home type reiserfs (rw)
/dev/vg01/lv_var on /var type reiserfs (rw)

ここで、このhome と var を含む主要なファイルシステムを、1日1回、増設した別のディスク(/dev/hdd)にrsyncを使ってバックアップすることにした。(home と var 以外のディレクトリ以下には、通常、保守時以外にはデータが書き込まれることはなく、データの増減もほとんどないため、LVMは適用していない) LVMを適用したhome と var については、バックアップ時にスナップショットを採取し、それをバックアップすることで、データの不完全性を排除する。手順としては、例えば、var のバックアップの場合、
lvremove -f /dev/vg01/snap_var
lvcreate --size 100m --snapshot --name snap_var /dev/vg01/lv_var
mount -r /dev/vg01/snap_var /mnt/snap/var
mount -t ext3 /dev/hdd1 /mnt/hdd1/var
rsync -a --delete /mnt/snap/var/ /mnt/hdd1/var/
umount /mnt/snap/var
lvremove -f /dev/vg01/snap_var

という感じで、/mnt/snap/var にマウントしたスナップショットを、バックアップ用ディスク側にマウントした/mnt/hdd1/var に差分コピーするわけであるが、この時、スナップショットをマウントする段階(上の例では3行目のmountコマンド)で、次のようなエラーが出てしまうのだ。
mount: wrong fs type, bad option, bad superblock on /dev/vg_01/snap_var,
       or too many mounted file systems
この時、syslogには、以下のメッセージが出力される。
----- /var/log/messages -----
Oct 23 10:17:31 papa kernel: reiserfs: checking transaction log
(device 3a:03) ...
Oct 23 10:17:31 papa kernel: clm-2076: device is readonly, unable to
replay log
Oct 23 10:17:31 papa kernel: Replay Failure, unable to mount
Oct 23 10:17:31 papa kernel: reiserfs_read_super: unable to initialize
journal space
----------------------------

VFS patchの適用

その後の調査で、この不具合は、reiserfsやext3などのジャーナリングファイルシステムを適用したLVに対するスナップショットのマウント時に発生することがわかった。ただし、初期化直後のLVでは正常にマウントできるものの、初期化後、ファイルシステムを作成したLVに対しては、この不具合が発生することが確認できた。
LVM回りのカーネルソースを追っかける技量はないので、正確な原因はわからないが、(ジャーナリングの関係でr/w openをかけようとしてエラーになってるのか?)、これに対処するためのカーネルパッチとして、VFS-lock.patch なるものがLVMのパッケージに同梱されているのがわかった。kernel 2.4.19 に対応した linux-2.4.19-VFS-lock.patch をカーネルに当てた後、再度、カーネルを再構築してみると、思った通り、不具合は解消された。(かのように見えた)。

バックアップスクリプトによる(苦し紛れの)対処

ディスクのバックアップ処理は、crondにより、毎日1回実行されるように、スクリプトを作成し、/etc/cron.daily に登録している。VFS patch の適用後、数日、動作状況をwatchしていたが、タイミングによって、以前と同様の不具合が出る場合があることが判明した。どういう場合やタイミングで出るのかは不明であるが、何回かリトライすればマウントできることから、何らかの対策パッチが出るまでは、(fakeだけど)、エラーを検出した場合にリトライするように、スクリプトで対応するようにした。(以下参考)
#!/bin/sh
export PATH=/usr/local/bin:/usr/bin:/bin
export LANG=C
LIST1="var home"
LIST2="bin boot dev etc initrd lib misc opt root sbin usr"
DAY=`date "+%A"`

mount -t ext2 /dev/hdd1 /mnt/hdd1
mount -t ext3 /dev/hdd5 /mnt/hdd1/usr
mount -t ext3 /dev/hdd7 /mnt/hdd1/var
mount -t ext3 /dev/hdd8 /mnt/hdd1/home
mount -t ext3 /dev/hdd9 /mnt/hdd9

cd /mnt/hdd1
for d in $LIST1; do
    tar cvzf /mnt/hdd9/$DAY/$d.tar.gz $d > /dev/null 2> /dev/null
    RC=1
    CTR=0
    until [ $RC = 0 -o $CTR = 10 ]
    do
        /sbin/lvremove -f /dev/vg01/snap_$d > /dev/null 2> /dev/null
        /sbin/lvcreate --size 100m --snapshot --name snap_$d /dev/vg01/lv_$d  > /dev/null 2> /dev/null
        mount -r /dev/vg01/snap_$d /mnt/snap/$d
        RC=$?
        CTR=`expr $CTR + 1`
    done
    echo "hdsync: Volume /dev/vg_01/snap_$d mounted after $CTR time(s) trial"
    rsync -a --delete --exclude cache /mnt/snap/$d/ /mnt/hdd1/$d/
    umount /mnt/snap/$d
    /sbin/lvremove -f /dev/vg01/snap_$d > /dev/null 2> /dev/null
done
cd /

for d in $LIST2; do
    rsync -a --delete --exclude cache /$d/ /mnt/hdd1/$d/
done

umount /mnt/hdd9
umount /mnt/hdd1/home
umount /mnt/hdd1/var
umount /mnt/hdd1/usr
umount /mnt/hdd1

さいごに

現在のところ、3日〜4日に1回ぐらいの頻度で、マウントエラーがでるものの、この仕組みで2回リトライすれば、正常にマウントされているようだ。根本的な解決にはなっていないけれど、とりあえずはこれでよしとするか。。
ちなみに、同様の現象は、Turbolinuxでも確認された。本製品は、LVMもreiserfsも共に正式にサポートする旨うたっているものの、組み合わせた場合のsnapshotまでは動作検証していないみたいで、サポートセンターに問い合わせても、今のところ回避方法なし、という回答しか得られなかった。一応、bugzillaには登録しておいたけど、次期バージョンではちゃんと対応してくれるんだろうか??
ちなみに、turbolinux server では、インストーラでLVMによるファイルシステム構築をサポートしており、非常に簡単にLVMを導入できる。が、しかし、LVMで構築したシステムに対するアップグレードインストールは*できない*。 例えば、私の場合、Turbolinux Server 6.5でファイルシステムに LVM + reiserfs を適用しインストールしたシステムに対し、Turbolinux 7 server のアップグレードインストールを実行した場合、パーティション設定の直前でインストーラが異常終了した。
これに対する、turbolinuxの回答は以下の通り。
-----
誠に申し訳ございませんが、インストーラであるmongooseはもともと
LVMにインストールを行うことを想定して作成されておりません。
従いまして、現状ではLVMに対してインストールを行うことは出来ません。
今後対応させる予定はございませんが、何卒ご了承ください。
-----
LVMやreiserfsに対応している、という売り文句とは裏腹に、こういった不具合(仕様?)については、マニュアル等にもいっさい出ていないので、turbolinuxでLVMの適用をお考えの方は十分注意されたい。(なお、「LVMに対してインストールを行うことが出来ない旨は今後マニュアル等に反映させて頂きたいと思います。」との回答があったので、今後、何らかの対応があることを期待したい。)

補足

その後、kernelを2.4.22(Vine Linux 2.6r3用のkernel-2.4.22-0vl2.8)に更新 したところ、このエラーは出なくなったようです。

Copyright (c) 2002-2004 Ryoichi "Rio" MURASHIMA
[戻る] [R!o Interactive top]