ZFS linux + 独自カーネル

# ZFS を Scientific Linux 6 (CentOS 6) 独自コンパイルのカーネルにインストールする

Linux カーネルをパッケージで利用しているときは、 [ZFS についてもレポジトリを登録後](https://github.com/zfsonlinux/zfs/wiki/RHEL-and-CentOS) yum install で簡単にインストールでき、問題がおきてもパッケージの削除後、再インストールでまた復活します。
ZFS は DKMS[^1]モジュールで提供されます。さらに、ZFS は SPL[^2] 上で動きますが、SPL も DKMS モジュールです。
ここで、新しい Linux カーネルを使いたいとかでやむなく独自でコンパイルして導入しても、DKMS の仕組みで勝手にコンパイルしてモジュールが生成されます。うまく動いているうちは。でも、独自でコンパイルカーネルで、よくわからない理由で ZFS モジュールが認識されくなった時は、パッケージの削除後、再インストールで復活するのかといえば容易ではないようで、とはいえ、どこの質問の回答も自分でカーネル入れただろ（そんなの面倒見るかい）とかパッケージの削除後、再インストールしなさいという回答です。つまり、参考にならないということです。
[^1]: Dynamic Kernel Module Support (DKMS) はカーネルのソースツリーの外にソースが存在する Linux カーネルモジュールの生成を可能にするプログラム/フレームワークです。新しいカーネルがインストールされたときに DKMS モジュールは自動的にリビルドされます。 [archlinux](https://wiki.archlinux.jp/index.php/Dynamic_Kernel_Module_Support)
[^2]: The Solaris Porting Layer (SPL) is a Linux kernel module which provides many of the Solaris kernel APIs. [packages.debian.org](https://packages.debian.org/sid/kernel/spl)
ということで、独自でコンパイルカーネルでの ZFS 復活方法を紹介しておきます。

## 環境

ZFS を使っている linux pc は Scientific Linux release 6.9 (Carbon) で、下記 3 種類のカーネルで起動可能ですが、現在は 3.18.3 を使用しています

* 2.6.32-504.3.3 （パッケージからインストール、カーネルソース /usr/src/kernels /2.6.32-504.3.3.el6.x86_64）
* linux-3.14.29 （独自コンパイル、カーネルソース /usr/local/src/linux-3.14.29）
* linux-3.18.3 （独自コンパイル、カーネルソース /usr/local/src/linux-3.18.3）

保守停電を忘れていて、電源断になった liunux pc を再起動したときには zfs, zpool が動かなくなってました。

### SPL と ZFS のバージョン

ちょっと古いですが、0.6.5.11 を使用します。

## SPL, ZFS の DKMS のモジュールを消す

まず、DKMS モジュールがどうなっているのか調べようにもエラーとなってました。

```shell-session
# dkms status
Error! Could not locate dkms.conf file.
File: does not exist.
```

dkms.conf がどこにあるかというと、

* SPL は、/var/lib/dkms/spl/0.6.5.11/source/dkms.conf （0.6.5.11 は SPL のバージョン）
* ZFS だと、/var/lib/dkms/zfs/0.6.5.11/source/dkms.conf （0.6.5.11 は ZFS のバージョン）

にあります。source は、それぞれ、 /usr/src/spl-0.6.5.11/ と /usr/src/zfs-0.6.5.11/ へのシンボリックリンクで、 /usr/src/spl-0.6.5.11/ は、 spl-dkms パッケージ、 /usr/src/zfs-0.6.5.11/ は、zfs-dkms パッケージに属します。
spl-dkms もしくは zfs-dkms パッケージを削除時には、/var/lib/dkms/ 以下も整理してくれるのですが、/var/lib/dkms/ 以下がパッケージ管理外ということもあり、ZFS のアップデートを繰り返していると、なぜか整合が取れなくなるときがあるようです。今回は、source の参照先が /usr/src で、パッケージ管理されているファイルを知らずに消していたこともあり、ますますファイルの整合がとれなくなっていました。

そこで、/var/lib/dkms/ 以下をきれいにします。
まず、どうせ ZFS が動かないのですから、ZFS と SPL パッケージ関連パッケージをすべて削除します:

```shell-session
# yum remove zfs zfs-dkms libzfs2 libnvpair1 libuutil1 libzpool2 spl spl-dkms spl-kmod kmod-spl-devel
```
%preun とか %postun （RPM アンインストール時に実行するスクリプト）で失敗して、アンインストールできないときはスクリプトを動かさない削除をします:

```shell-session
# rpm -e --noscripts パッケージ名
```

次に、SPL, ZFS のカーネルモジュールを /var/lib/dkms/ から削除します。いままでアップデートした歴代カーネルモジュールも残っていたりもするので（起動時にカーネルモジュールが生成されるため、パッケージ管理外となる）これらもすべて消します:

```shell-session
# rpm -rf /var/lib/dkms/spl /var/lib/dkms/zfs
```

## カーネルの整理

spl-kmod, zfs-dkms パッケージをインストールするときに grub でブート可能なカーネルすべてに対しカーネルモジュールを作りにいきます。ですから、grub でブート可能なカーネルすべてについて、カーネルソースをインストールしておかないとなりません。
具体的には kernel-headers, kernel-devel がかけている kernel は削除します（もしくは、kernel-headers, kernel-devel を追加）。

#### パッケージからインストールされているカーネル

例えば、kernel-headers とか、kernel-devel がそろっていればいいのですが（下はそろっている例です）:

```shell-session
# rpm -qa | grep kernel
kernel-2.6.32-504.3.3.el6.x86_64
kernel-devel-2.6.32-504.3.3.el6.x86_64
kernel-firmware-2.6.32-504.3.3.el6.noarch
dracut-kernel-004-409.el6_8.2.noarch
kernel-headers-2.6.32-696.23.1.el6.x86_64
```

kernel-2.6.32-504.3.3.el6.x86_64 だけが存在し、kernel （または DKMS モジュール）のコンパイルに必要な kernel-devel, kernel-headers がないときは、次のふたとおりの手立てがあります:

* kernel-2.6.32-504.3.3.el6.x86_64 を消してしまう
* kernel-devel, kernel-headers を追加する

#### 独自インストールしたカーネル

独自でカーネルをコンパイルしているときは、カーネルソースはそのままにしておく必要があります。もしカーネルソースを消してしまっていたら、ソースからカーネルを入れなおすか、grub からブート可能なカーネルから除外します。
今使っている（使いたい）カーネルのカーネルソースを消去してしまっているときは、選択肢はりません。もう一度ソースから入れなおしましょう。

## ZFS RPM パッケージを作る

### 準備

https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.6.5.11 から
spl-0.6.5.11.tar.gz と zfs-0.6.5.11.tar.gz をダウンロードし、任意のディレクトリに展開します。ここでは /usr/local/src/zfs 以下に展開しています。

```shell-session
# cd /usr/local/src/zfs
# tar xvfz ~/Download/spl-0.6.5.11.tar.gz
# tar xvfz ~/Download/zfs-0.6.5.11.tar.gz
```
gcc などが入っていなかったらコンパイルに必要なパッケージ群を一括インストールします:

```shell-session
# yum groupinstall "開発ツール"
```

このほか make rpm 時にパッケージが足りなければ適宜インストールしてください。

### spl の RPM パッケージを作ってインストール


```shell-session
# cd /usr/local/src/zfs/spl-0.6.5.11
# ./autogen.sh
# ./configure
# make rpm
```

ZFS のパッケージ作成でも必要なので、必要な SPL パッケージをインストールします:

```shell_session
# rpm -ivh spl-dkms-0.6.5.11-1.el6.noarch.rpm spl-0.6.5.11-1.el6.x86_64.rpm
準備中...                ########################################### [100%]
   1:spl-dkms               ########################################### [ 50%]
Loading new spl-0.6.5.11 DKMS files...
It is likely that 3.18.3 belongs to a chroot's host
Building for 2.6.32-504.3.3.el6.x86_64, 3.14.29 and 3.18.3
Building initial module for 2.6.32-504.3.3.el6.x86_64
Done.

spl:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.32-504.3.3.el6.x86_64/extra/

splat.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.32-504.3.3.el6.x86_64/extra/
Adding any weak-modules

depmod...

DKMS: install completed.
Building initial module for 3.14.29
Done.

spl:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/3.14.29/extra/

splat.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/3.14.29/extra/
Adding any weak-modules

depmod...

DKMS: install completed.
Building initial module for 3.18.3
Done.

spl:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/3.18.3/extra/

splat.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/3.18.3/extra/
Adding any weak-modules

depmod...

DKMS: install completed.
   2:spl                    ########################################### [100%]
```

ちゃんと spl の DKMS モジュールが入っているかどうか確認します:

```shell-session
# dkms status
spl, 0.6.5.11, 2.6.32-504.3.3.el6.x86_64, x86_64: installed
spl, 0.6.5.11, 3.14.29, x86_64: installed
spl, 0.6.5.11, 3.18.3, x86_64: installed
```

### ZFS の RPM パッケージを作ってインストール

```shell-session
# cd /usr/local/src/zfs/zfs-0.6.5.11/
# ./configure --with-spl=/usr/src/spl-0.6.5.11 --with-spl-obj=/var/lib/dkms/spl/0.6.5.11/3.18.3/x86_64/
# make rpm
--------------- 略 ---------------
Installing zfs-kmod-0.6.5.11-1.el6.src.rpm
error: Failed build dependencies:
        kmod-spl-devel = 0.6.5.11 is needed by zfs-kmod-0.6.5.11-1.el6.x86_64
make[1]: *** [rpm-common] エラー 1
make[1]: ディレクトリ `/usr/local/src/zfs/zfs-0.6.5.11' から出ます
make: *** [rpm-kmod] エラー 2
```

必要なパッケージを入れ:

```shell-session
# rpm -ivh ../spl-0.6.5.11/kmod-spl-devel-0.6.5.11-1.el6.x86_64.rpm
```

もう一回挑戦:

```shell-session
# make rpm
# rpm -ivh zfs-0.6.5.11-1.el6.x86_64.rpm zfs-dkms-0.6.5.11-1.el6.noarch.rpm libzfs2-0.6.5.11-1.el6.x86_64.rpm libnvpair1-0.6.5.11-1.el6.x86_64.rpm libuutil1-0.6.5.11-1.el6.x86_64.rpm libzpool2-0.6.5.11-1.el6.x86_64.rpm
準備中...                ########################################### [100%]
   1:libuutil1              ########################################### [ 17%]
   2:libnvpair1             ########################################### [ 33%]
   3:libzpool2              ########################################### [ 50%]
   4:libzfs2                ########################################### [ 67%]
   5:zfs-dkms               ########################################### [ 83%]
Loading new zfs-0.6.5.11 DKMS files...
It is likely that 3.18.3 belongs to a chroot's host
Building for 2.6.32-504.3.3.el6.x86_64, 3.14.29 and 3.18.3
Building initial module for 2.6.32-504.3.3.el6.x86_64
Done.

zavl:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.32-504.3.3.el6.x86_64/extra/

--------------- 略 ---------------
zpios.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/3.18.3/extra/
Adding any weak-modules

depmod...

DKMS: install completed.
   6:zfs                    ########################################### [100%]
```

ちゃんと spl の DKMS モジュールが入っているかどうか確認します:

```shell-session
# dkms status
spl, 0.6.5.11, 2.6.32-504.3.3.el6.x86_64, x86_64: installed
spl, 0.6.5.11, 3.14.29, x86_64: installed
spl, 0.6.5.11, 3.18.3, x86_64: installed
zfs, 0.6.5.11, 2.6.32-504.3.3.el6.x86_64, x86_64: installed
zfs, 0.6.5.11, 3.14.29, x86_64: installed
zfs, 0.6.5.11, 3.18.3, x86_64: installed (original_module exists)
```

### 動作確認

```shell-session
# zpool list
NAME     SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
export   425G   177G   248G         -      -    41%  1.00x  ONLINE  -
```

動いてます。

## トラブル

### それでも The ZFS modules are not loaded.

```shell-session
# zpool list
The ZFS modules are not loaded.
Try running '/sbin/modprobe zfs' as root to load them.
```

#### 対策:

1. リブートする →　OK なら終了
1. リブートしてもダメ → 以下実行しリブート:

```shell-session
# dkms remove -m zfs -v 0.6.5.11 --all
# dkms remove -m spl -v 0.6.5.11 --all
# dkms --force install -m spl -v 0.6.5.11
# dkms --force install -m zfs -v 0.6.5.11
```

### spf-dkms, zfs-dkms インストール、アンインストール時に大量に警告がでる

```shell-session
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/zfs.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/zpios.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/zunicode.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/znvpair.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/zavl.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/icp.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/spl.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/splat.ko: No such file or directory
WARNING: Can't read module /lib/modules/2.6.32-504.el6.x86_64/weak-updates/zcommon.ko: No such file or directory

egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/zfs.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/zpios.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/zunicode.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/znvpair.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/zavl.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/icp.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/spl.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/splat.ko: No such file or directory
egrep: /lib/modules/2.6.32-504.el6.x86_64//weak-updates/zcommon.ko: No such file or directory
```

#### 原因と対策

原因は、grub からブート可能なカーネルだが、カーネルヘッダーがまともにインストールされておらず、DKMS モジュールがビルドできないため。対応する kernel-devel, kernel-headers パッケージをインストールするか、カーネルパッケージを削除してください（上記であれば、kernel-2.6.32-504.el6.x86_64）。