FreeBSD Daily Topics

2011年9月21日ZFS活用シリーズ - scrubで直らない問題の修正(zdb - 状況調査編)

一度使い出したらその便利さに抜け出せなくZFS。ZFSの提供するさまざまな機能を使わなくても基本的な使い方だけでも便利なものですが、運用するうえでいくつか知っておくと便利なこともあります。数回だけ、そんなティップスを紹介していきます。

Do zdb for ZFS analysis

ZFSは壊れにくいファイルシステムだと言われてはいますが、なんらかの原因で壊れることもあります。スクラブで直らない場合にはzdb(1M)で直すのが順当な修正方法となります。ただし、zdb(1M)はそもそもZFSの開発者が利用するために提供されているものなので、ドキュメントもありませんし、動作の詳細を知りたい場合にはソースコードを読む必要があります。

ここではとくにzdb(1M)の使い方の中でも利用率が高いだろうと思われる方法を紹介しておきます。ただし、将来のバージョンで同じ処理がサポートされ続けるとは限らず、また、問題が発生しないとも限りません。使用する場合には開発者向けのコマンドであることを理解したうえで使用してください。

まず、問題が発生したプールはexportします。importした状態のまま処理を行うと処理がカーネルを経由するためにパニックしやすくなるからです。LiveCDから起動して処理を実施してもかまいません。最近のFreeBSDインストーラはZFSも扱うことができます。

「zdb -e -d プール」にてまずはプール内部の構成を確認します。

# zdb -e -d zpool
Dataset mos [META], ID 0, cr_txg 4, 116K, 46 objects
Dataset zpool/ports [ZPL], ID 37, cr_txg 8, 1.09G, 332771 objects
Dataset zpool [ZPL], ID 21, cr_txg 1, 31.0K, 7 objects
#

「-e」はexportされたプールであることを指定しています。importした状態であれば次のように「-e」をはずせば同じことが実施されます。ただし、importした状態での作業はお薦めできません。

# zdb -d zpool
Dataset mos [META], ID 0, cr_txg 4, 116K, 46 objects
Dataset zpool/ports [ZPL], ID 37, cr_txg 8, 1.09G, 332771 objects
Dataset zpool [ZPL], ID 21, cr_txg 1, 31.0K, 7 objects
#

「zdb -l デバイスファイル」を指定すれば直接プールの情報をチェックできます。プール名がわからない場合などはこちらを使ってプール名のチェックを実施します。

# zdb -l /dev/ada1
--------------------------------------------
LABEL 0
--------------------------------------------
    version: 28
    name: 'zpool'
    state: 0
    txg: 175
    pool_guid: 6769210400753061927
    hostid: 3333601617
    hostname: 'freebsd.ongs.co.jp'
    top_guid: 8290673747710924871
    guid: 8290673747710924871
    vdev_children: 1
    vdev_tree:
        type: 'disk'
        id: 0
        guid: 8290673747710924871
        path: '/dev/ada1'
        phys_path: '/dev/ada1'
        whole_disk: 1
        metaslab_array: 30
        metaslab_shift: 29
        ashift: 9
        asize: 85894627328
        is_log: 0
        create_txg: 4
--------------------------------------------
LABEL 1
--------------------------------------------
    version: 28
    name: 'zpool'
    state: 0
    txg: 175
    pool_guid: 6769210400753061927
    hostid: 3333601617
    hostname: 'freebsd.ongs.co.jp'
    top_guid: 8290673747710924871
    guid: 8290673747710924871
    vdev_children: 1
    vdev_tree:
        type: 'disk'
        id: 0
        guid: 8290673747710924871
        path: '/dev/ada1'
        phys_path: '/dev/ada1'
        whole_disk: 1
        metaslab_array: 30
        metaslab_shift: 29
        ashift: 9
        asize: 85894627328
        is_log: 0
        create_txg: 4
--------------------------------------------
LABEL 2
--------------------------------------------
    version: 28
    name: 'zpool'
    state: 0
    txg: 175
    pool_guid: 6769210400753061927
    hostid: 3333601617
    hostname: 'freebsd.ongs.co.jp'
    top_guid: 8290673747710924871
    guid: 8290673747710924871
    vdev_children: 1
    vdev_tree:
        type: 'disk'
        id: 0
        guid: 8290673747710924871
        path: '/dev/ada1'
        phys_path: '/dev/ada1'
        whole_disk: 1
        metaslab_array: 30
        metaslab_shift: 29
        ashift: 9
        asize: 85894627328
        is_log: 0
        create_txg: 4
--------------------------------------------
LABEL 3
--------------------------------------------
    version: 28
    name: 'zpool'
    state: 0
    txg: 175
    pool_guid: 6769210400753061927
    hostid: 3333601617
    hostname: 'freebsd.ongs.co.jp'
    top_guid: 8290673747710924871
    guid: 8290673747710924871
    vdev_children: 1
    vdev_tree:
        type: 'disk'
        id: 0
        guid: 8290673747710924871
        path: '/dev/ada1'
        phys_path: '/dev/ada1'
        whole_disk: 1
        metaslab_array: 30
        metaslab_shift: 29
        ashift: 9
        asize: 85894627328
        is_log: 0
        create_txg: 4
#

対象となるプールがパニックを誘発する状態にあるかどうかは次のように「zdb -e プール」で調査することができます。すべてのチェックが実施されるのできわめて大量のログが出力されます。

# zdb -e zpool
Configuration for import:
        vdev_children: 1
        version: 28
        pool_guid: 6769210400753061927
        name: 'zpool'
        state: 1
        hostid: 3333601617
        hostname: 'freebsd.ongs.co.jp'
        vdev_tree:
            type: 'root'
            id: 0
            guid: 6769210400753061927
            children[0]:
                type: 'disk'
                id: 0
                guid: 8290673747710924871
                phys_path: '/dev/ada1'
                whole_disk: 1
                metaslab_array: 30
                metaslab_shift: 29
                ashift: 9
                asize: 85894627328
                is_log: 0
                create_txg: 4
                path: '/dev/ada1'

MOS Configuration:
        version: 28
        name: 'zpool'
        state: 1
        txg: 229
        pool_guid: 6769210400753061927
        hostid: 3333601617
        hostname: 'freebsd.ongs.co.jp'
        vdev_children: 1
        vdev_tree:
            type: 'root'
            id: 0
            guid: 6769210400753061927
            children[0]:
                type: 'disk'
                id: 0
                guid: 8290673747710924871
                path: '/dev/ada1'
                phys_path: '/dev/ada1'
                whole_disk: 1
                metaslab_array: 30
                metaslab_shift: 29
                ashift: 9
                asize: 85894627328
                is_log: 0
                create_txg: 4

Uberblock:
	magic = 0000000000bab10c
	version = 28
	txg = 229
	guid_sum = 15059884148463986798
	timestamp = 1316524683 UTC = Tue Sep 20 22:18:03 2011

All DDTs are empty

Metaslabs:
	vdev          0
	metaslabs   159   offset                spacemap          free      
	---------------   -------------------   ---------------   -------------
	metaslab      0   offset            0   spacemap     33   free    23.0M
	                  segments        190   maxsize    733K   freepct    4%
	metaslab      1   offset     20000000   spacemap     42   free    19.7M
	                  segments        201   maxsize   8.95M   freepct    3%
	metaslab      2   offset     40000000   spacemap     44   free     447M
	                  segments         44   maxsize    441M   freepct   87%
	metaslab      3   offset     60000000   spacemap     46   free     512M
	                  segments          5   maxsize    512M   freepct   99%
	metaslab      4   offset     80000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab      5   offset     a0000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab      6   offset     c0000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab      7   offset     e0000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab      8   offset    100000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab      9   offset    120000000   spacemap      0   free     512M
	                  segments          1   maxsize    512M   freepct  100%
	metaslab     10   offset    140000000   spacemap      0   free     512M
....

これまでの操作が実施できない場合、次のように/dev/dskというリンクファイルを作成してから作業してみてください。FreeBSDでは/devに仮想デバイスが展開されますが、Solarisでは/dev/dskに仮想デバイスが展開されているため、zdbがそちらをチェックしに行って失敗している可能性があります。最新版では修正されていると思いますが、再び同じ状況に戻るとも限らないのでこの方法は覚えておくと便利です。

cd /dev; ln -s . dsk

プールの状況を調べる基本的なzdb(1M)の使い方はこんなところです。これ以上深入りする必要があるようだと、なにかと失敗する可能性が出てくるのでこのあたりで止めておいたほうが良いでしょう。

おすすめ記事

記事・ニュース一覧