2014年7月26日

NFSトラブル Fedora 13/14 nobody:nobody

Fedora 13(FC13)上のVMPlayerで走らせているFedora 14(FC14)がブートしなくなった。原因は不明。ブーとの最中にカーネルがパニックを起こす。

 幸いなことにすべてのバックアップが揃っているので、FC14のイメージをVMPayerで再インストールし、バックアップから必要なファイルを回復させる。わけの分からないVMPlayerのイメージファイルと格闘するよりずっと手っ取り早いという判断。もともとこのFC14はFC14をターゲットにしたプロジェクトのビルドだけを目的として、その他の汎用性はまったく求めていないのでカスタマイズした部分もわずかだ。

エディタやバックアップなどのファイル管理は、すべてセントラルサーバであるFC13に任せ、FC14はプロジェクトの開発ディレクトリのみをNFSマウントして、ビルド作業だけを実行する。以前は/home をまるごとマウントしていたが、ホームディレクトリのしたの種々の設定ファイルがぶつかるとあまりおもしろくないので、プロジェクトの開発ディレクトリだけをマウントすることにした。

ところが通常どおり/etc/fstab にNFSのマウントを記述するとマウントはするが、マウントポイント以下のファイルの所有者がすべて nobody:nobody になってしまう。 このマウントされるサーバのディレクトリは他のマシンにもマウントされているが、そちらは正常なファイルの所有者になっている。このままでは用をなさない。

条件をまとめてみる。
  • FC13がNFSサーバ
    /home/h/project をエfc14にクスポート(rw,wdelay,no_root_squash,no_subtree_check)
  • FC14がNFSクライアント
    mount -t nfs4 fc13:/home/h/projects /home/h/projects
  • FC13とFC14のユーザ「h」は同じID(501)
  • マウントは成功するが、FC14上でマウントしたディレクトリを見るとファイル所有者が nobody:nobody になっている
調査の結果、こちらからの情報が役に立った。

クライアント(FC14)の /etc/idmapd.conf を編集して


#Domain = localdomain.edu

の部分を

Domain = mydomain.edu

のように本物のドメイン(でなければならないのかどうかは不明)に書き換え、

# service rpcidmapd restart

を実行し、マウントをし直す。これでマウントされたディレクトリとその下のファイルが正しいファイル所有者になった。

今回はマウントするファイルの所有者がただ一人だったから、FC14側の ユーザIDをFC13側のIDと一致するように手で書き換えたが、複数のユーザIDが存在するならNISを使うのがよいと思う。

2014年6月17日

Fedora 20: VNC で MATE を走らせる

我が家のサーバ群は4年ほど前に構築した32ビットのFedora 13(FC13)ベース。さすがにいろいろなところが古くなってきたので、最新のFedroraに更新を計画しているが、実際の更新に先立って、まず現在のところ最新のFC20でテスト用サーバを1台作っている。

この戦略は正しかった。FC13とFC20ではあまりにもいろいろなところが違いすぎる。これから違いを一つ一つ確認していくが、取りあえず多くの違いの元凶一つとしてとして見つかったのは、SystemVのスタートアップスクリプトからsystemdへの変更。

今回はVNCサーバをやっつける。

小生はFC15から標準デスクトップになったGNOME3は生理的に合わない。小生のデスクトップの使用はXTerminalでCUIの作業が主体だから、ああ言うWindows8に迎合したようなデスクトップは使えない。実を言うと、GNOME2に固執しているのがFC13から4年間も更新を躊躇していた原因。しかし最近のリリースではGNOME2の後継のMATEが選べるようになったので漸く腰をあげた。

で、ローカルのデスクトップは指示どおりにインストールして何事もなく動作し、GNOME2風のデスクトップで安心したのだが、VNCで躓いた。

systemd以前のVNCサーバは /etc/sysconfig/vncserver に起動したいVNCセッションを書き込んでサービスを起動すればよかったが、systemd になって手順が変わった。以下が大まかなフロー。
  1. /usr/lib/systemd/system/vnserver@.service/etc/systemd/system/vncserver@:n.service にコピー(nは1~の任意の数字。5900+n がサーバのポート番号になる)
  2. /etc/systemd/system/vncserver@:n.service を編集。ほとんどの場合、<USER>を任意のユーザ名に変更するだけ。画面解像度の指定は、/usr/bin/vncserver のコマンドラインに以下のように)。

    ##ExecStart=/sbin/runuser -l <USER> -c "/usr/bin/vncserver %i"
    ExecStart=/sbin/runuser -l vncuser -c "/usr/bin/vncserver -geometry 1280x720 %i"
  3. vncpasswd を実行して ~/.vnc ディレクトリとパスワードファイルを作成。
  4. ~/.vnc/xstart を編集して望みのデスクトップ(ウィンドウマネージャ)を指定。
上記の1~3はいろいろなところで解説されているが、4.のデスクトップの指定は試行錯誤の結果。

MATEを指定するには、簡単に言えば、~/.vnc/xstart の内容を全部無視して、以下の一行を実行させるようにすればよい。
exec mate-session &
 具体的には、~/.vnc/xstart の内容を全部削除あるいはコメントアウトして上記の行をいれるか、または上記の行をファイルの先頭に挿入するだけ。

簡単なことほどどこにも書かれていないので見つけるのに苦労する。

2014年6月14日

BTRFS の RAID 機能

BTRFSはRAID機能を内蔵している。

LinuxのRAIDはmdの使用が一般的だが、今回は以前報告した「BTRFSのFIEMAP/filefragは嘘をつく」と併せてこの内部RAID機能を検証する。

検証に使った 3.0.101カーネルは以下のRAIDレベルをサポートする。
  • JBOD - リニアな複数ディスクの結合。冗長性なし
  • RAID0 - ストライピングによるアクセス性能向上。冗長性なし
  • RAID1 - ミラーリング。100%冗長
  • RAID10 - RAID0 を RAID1上で動作。ストライピングによるアクセス性能向上と100%の冗長性
上記より新しいカーネルではRAID5(水平パリティ)とRAID6(二重水平パリティ)も実現されているが、BTRFSのWikiにはまだ開発中でバグが多いので使用するな、と警告がある。

まず、実験のためにloopデバイスを二つ作り、JBODをマウントする。

root@h-rn312:~# truncate -s 100M /data/img/loop-img.0 /data/img/loop-img.1
root@h-rn312:~# losetup /dev/loop0 /data/img/loop-img.0
root@h-rn312:~# losetup /dev/loop1 /data/img/loop-img.1
root@h-rn312:~# mkfs.btrfs -f /dev/loop0 /dev/loop1 
SMALL VOLUME: forcing mixed metadata/data groups
WARNING! - Btrfs v3.14.1 IS EXPERIMENTAL

WARNING! - see http://btrfs.wiki.kernel.org before using

Performing full device TRIM (100.00MiB) ...

Turning ON incompat feature 'mixed-bg': mixed data and metadata block groups
Created a data/metadata chunk of size 8388608
Performing full device TRIM (100.00MiB) ...
adding device /dev/loop1 id 2
fs created label (null) on /dev/loop0
    nodesize 4096 leafsize 4096 sectorsize 4096 size 200.00MiB
Btrfs v3.14.1
root@h-rn312:~# mount -o rw /dev/loop0 /mnt
mount: block device /dev/loop0 is write-protected, mounting read-only
root@h-rn312:~# mount -o remount,rw /dev/loop0 /mnt


mkfs時に二つのディスクデバイスを組み合わせる(デフォルトはJBOD)ことを宣言しているので、マウントはどちらのデバイス名でもよい。後から「btrfs device add /dev/loop2 /mnt」のように追加もできる。一回目のマウントが読み出しオンリーになってしまったが理由は不明。

複数ディスクを使ってBTRFSのRAIDを構築・構成する方法の詳細はBTRFSのWikiを参照してください。

これに50MBのダミーのファイルを作る。

root@h-rn312:~# dd if=/dev/urandom of=/mnt/jbod bs=1M count=50

このファイルをfilefragでエクステントの状況を見る。使ったのは最新のe2fsprogs-1.42.10からビルドしたfilefrag。以前のバージョンより冗長な出力を見せる。

root@h-rn312:~# filefrag -v /mnt/jbod
Filesystem type is: 9123683e
File size of /mnt/jbod is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    3199:       3072..      6271:   3200:          
   1:     3200..    7999:       8192..     12991:   4800:       6272:
   2:     8000..   12799:      13312..     18111:   4800:      12992: eof
/mnt/jbod: 3 extents found

しかし、ここで表示されるFIEMAPioctl出力の「物理オフセット」は「BTRFSのFIEMAP/filefragは嘘をつく」で報告したようにBTRFSが内部で使う「論理オフセット」(filefragのファイル「論理オフセット」と混同しないこと)で、実際の物理ディスクのオフセット(位置)とは関係ない。

そこで特別にパッチを当てたカーネルとfilefragを使って本当の物理ディスクオフセットを見てみる。
root@h-rn312:~# filefrag -v -P /mnt/jbod
Filesystem type is: 9123683e
File size of /mnt/jbod is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..    3199:        256..      3455:   3200:   7:1
   1:     3200..    7999:       3072..      7871:   4800:   7:0
   2:     8000..   12799:       5376..     10175:   4800:   7:1   eof
/mnt/jbod: 3 extents found

device」フィールドは実際に使用されている物理ディスク(この場合はloopデバイス)のメジャー:マイナー・デバイス番号。これを見ると、ファイルはloop0デバイスとloop1デバイスにストライプ的に分散されており、普通「JBOD」でイメージする単純なリニア結合とは違い、むしろ複数ディスクからなるストレージプールにパフォーマンスを考慮した分散と解釈するのが適当のようだ。

続いて、同じようにして3台のディスクからなるRAID0(ストライピング)を試してみる(ここではloopデバイスでなく/dev/sdb*を使ったのでデバイス番号がJBODの例と違うが、うまく脳内変換してください)。

root@h-rn312:~# filefrag -v /mnt3/raid0
Filesystem type is: 9123683e
File size of /mnt3/raid0 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..   12799:       7158..     19957:  12800:             eof
/mnt3/raid0: 1 extent found
root@h-rn312:~# filefrag -v -P /mnt3/raid0
Filesystem type is: 9123683e
File size of /mnt3/raid0 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..   12799:       1622..      5887:   4266:   8:21  eof
   0:        0..   12799:       1616..      5887:   4272:   8:20  eof
   0:        0..   12799:       4432..      8693:   4262:   8:19  eof
/mnt3/raid0: 1 extent found
root@h-rn312:~# filefrag -v -P -X /mnt3/raid0
Filesystem type is: 9123683e
File size of /mnt3/raid0 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..    31ff:        656..      16ff:   10aa:   8:21  eof
   0:        0..    31ff:        650..      16ff:   10b0:   8:20  eof
   0:        0..    31ff:       1150..      21f5:   10a6:   8:19  eof
/mnt3/raid0: 1 extent found

物理エクステントの出力を見ると、/mnt/raid0ファイルの1論理エクステント(0~12799)に3物理エクステントが/dev/sdb[1-3](8:19~8:21)に分散して対応しており、filefragの出力からは分からないが各ストライプの長さは64KB(16ページブロック)。物理エクステントは連続してファイル内容を保持してはおらず、ストライプの続きは次のディスクのストライプに連続して、ディスクの使用は論理エクステントの終端まで循環する。

eof」のフラグは filefragが単に最終論理エクステントに表示するだけなのであまり意味はない

-Xオプションをつけた16進表示も見ると、物理エクステントの開始オフセットは3台のディスクで揃っていないどころか、ストライプの境界にも揃っておらず、さらには長さもバラバラなことが分かり、mdのディスク・アドレス空間で一様なストライピングとは様相が違うことが分かる。

次は2台のディスクを使ったRAID1(ミラーリング)。

root@h-rn312:~# filefrag -v /mnt2/raid1
Filesystem type is: 9123683e
File size of /mnt2/raid1 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    6399:       5129..     11528:   6400:          
   1:     6400..    9599:      11529..     14728:   3200:          
   2:     9600..   12799:      21504..     24703:   3200:      14729: eof
/mnt2/raid1: 2 extents found
root@h-rn312:~# filefrag -v -P /mnt2/raid1
Filesystem type is: 9123683e
File size of /mnt2/raid1 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..    6399:       2313..      8712:   6400:   8:18
   0:        0..    6399:       5129..     11528:   6400:   8:17
   1:     6400..    9599:       8713..     11912:   3200:   8:18
   1:     6400..    9599:      11529..     14728:   3200:   8:17
   2:     9600..   12799:      18688..     21887:   3200:   8:18  eof
   2:     9600..   12799:      21504..     24703:   3200:   8:17  eof
/mnt2/raid1: 3 extents found

三つの論理エクステントのそれぞれが 2台のディスクの同じサイズの物理エクステントで構成されているのはよいとしても、ペアになる物理エクステントの開始オフセットは揃っていない。どうもmdのような完全ディスクレベルのミラーリングとは違い、ファイルエクステント単位のRAIDを実現していることがますますはっきりしてきた。

最後はRAID10。最低4台のディスクが必要(mdでは3台でもRAID10を実現できる)。

root@h-rn312:~# filefrag -v /mnt4/raid10
Filesystem type is: 9123683e
File size of /mnt4/raid10 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..   12799:       7174..     19973:  12800:             eof
/mnt4/raid10: 1 extent found
root@h-rn312:~# filefrag -v -P /mnt4/raid10
Filesystem type is: 9123683e
File size of /mnt4/raid10 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..   12799:       2310..      8709:   6400:   8:25  eof
   0:        0..   12799:       2310..      8709:   6400:   8:24  eof
   0:        0..   12799:       2304..      8703:   6400:   8:23  eof
   0:        0..   12799:       5120..     11519:   6400:   8:22  eof
/mnt4/raid10: 1 extent found

RAID1と同様、物理オフセットは揃っていない。

さらに動作を検証すると、RAID機能はリアルタイムではなく、一旦普通のシングルディスクファイルで展開されたエクステントをバックグラウンドでRAIDに再構築しているようだ。

下は、RAID0にファイルを作成した直後と10秒ほど経ってからの物理エクステントの様子。最初は/dev/sdb1だけで作られたファイルが/dev/sdb[1-3]に分散される様子が見える。

root@h-rn312:~# ./filefrag -v -P /mnt3/raid0
Filesystem type is: 9123683e
File size of /mnt3/raid0 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..    1023:          0..      1023:   1024:   8:19
   1:     1024..    2047:          0..      1023:   1024:   8:19
   2:     2048..    3071:          0..      1023:   1024:   8:19
   3:     3072..    4095:          0..      1023:   1024:   8:19
   4:     4096..    5119:          0..      1023:   1024:   8:19
   5:     5120..    6143:          0..      1023:   1024:   8:19
   6:     6144..    7167:          0..      1023:   1024:   8:19
   7:     7168..    8191:          0..      1023:   1024:   8:19
   8:     8192..    9215:          0..      1023:   1024:   8:19
   9:     9216..   10239:          0..      1023:   1024:   8:19
  10:    10240..   11263:          0..      1023:   1024:   8:19
  11:    11264..   12287:          0..      1023:   1024:   8:19
  12:    12288..   12799:          0..       511:    512:   8:19  eof
/mnt3/raid0: 13 extents found
root@h-rn312:~# ./filefrag -v -P /mnt3/raid0
Filesystem type is: 9123683e
File size of /mnt3/raid0 is 52428800 (12800 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length: device: flags:
   0:        0..   12799:       1622..      5887:   4266:   8:21  eof
   0:        0..   12799:       1616..      5887:   4272:   8:20  eof
   0:        0..   12799:       4432..      8693:   4262:   8:19  eof
/mnt3/raid0: 1 extent found

と言うことで、BTRFSのRAID機能は、その実現方法がファイルシステムに依存しているらしいことが分かった(当然か)。LVMなしでJBODが簡単に実現できることはメリットがあるが、「本物の」RAID機能はBTRFS内部で一体化しておりレイヤの切り分けができないので、システムの拡張とか事故が起きたときの 対応はどうだろうかという疑問が残る。得てしてこう言う「一体型」ソリューションは、そのシステムが想定しているモデルから少しでも外れると途端に使いにくくなるもの、と言う経験則からは躊躇する。

2014年5月28日

アトミック・カーネルスレッドと言うものがあるらしい

BTRFSのディスクからの読み込み終了時の関数 btrfs_readpage_end_io_hook() をいじっている。

目的とした機能が動作して最終テストを行っていたら、dmesg が下のように文句を言っている。

BUG: scheduling while atomic: btrfs-endio-1/1157/0x00000001
Modules linked in:
Pid: 1157, comm: btrfs-endio-1 Not tainted 3.0.101.RNx86_64.2.2+ #121
Call Trace:
 [<ffffffff8887d4bd>] ? __schedule_bug+0x54/0x58
 [<ffffffff8888712b>] ? __schedule+0x59b/0xa30
 [<ffffffff88398299>] ? put_dec+0x59/0x60
 [<ffffffff880d0be4>] ? add_partial+0x24/0x80
 [<ffffffff880d240e>] ? deactivate_slab+0x4e/0xf0
 [<ffffffff88774849>] ? __alloc_skb+0x99/0x270
 [<ffffffff8888768a>] ? schedule+0x3a/0x50
 [<ffffffff88042e6d>] ? sys_sched_yield+0x3d/0x50
 [<ffffffff888878bf>] ? yield+0x2f/0x40
 [<ffffffff88799ea0>] ? netlink_broadcast_filtered+0x330/0x480
 [<ffffffff8879a009>] ? netlink_broadcast+0x19/0x20
 [<ffffffff883ad39e>] ? nla_put+0x2e/0x40
 [<ffffffff883488af>] ? mdcsrepair_netlink+0x46f/0x580
 [<ffffffff882e6711>] ? btrfs_readpage_end_io_hook+0x1d1/0x3a0
 [<ffffffff882fd64e>] ? end_bio_extent_readpage+0x12e/0x9c0
 [<ffffffff88106fe8>] ? bio_endio+0x18/0x30
 [<ffffffff882d864f>] ? end_workqueue_fn+0x3f/0x50
 [<ffffffff8830d3f0>] ? worker_loop+0x140/0x500
 [<ffffffff8830d2b0>] ? btrfs_queue_worker+0x300/0x300
 [<ffffffff88063a09>] ? kthread+0x89/0x90
 [<ffffffff8888aa74>] ? kernel_thread_helper+0x4/0x10
 [<ffffffff88063980>] ? kthread_worker_fn+0x140/0x140
 [<ffffffff8888aa70>] ? gs_change+0xb/0xb


調べてみると、in_atomic_preempt_off() が真になっていることが直接の原因。どうもこのワーカースレッドはプリエンプションだけでなくスケジューリングも禁止しており、スレッドとは言え、割り込み処理のようにCPUを手放さずにスレッド終了まで実行しなければならないようだ。このコールスタックでは nla_put()(Netlinkのメッセージ構築関数)がスケジュールしてしまうためにバグとしてスタックダンプをしている。実際にはスタックダンプがあっても目的の機能は実行されて問題がないのだが、そこはホレ、やはりこういうものは出現させるべきではない。

解決策としては、 nla_put()をやめる訳には行かず、またこのスレッドをノン・アトミックにするのもはばかれるので、一計を案じてアトミックでない通常のスレッドを別に走らせてそこに必要なデータを渡してnla_put()以降の処理を依頼することにした。ここでは無限ループのサービススレッドでうまく行ったが、1回限りのワーカースレッドでもうまく行くかどうかは試していない。

2014年5月13日

古いラップトップの延命策 - 802.11n と HDDからSSDへの換装

小生が家でメインに使っているPCはDELLのXPS M1330というラップトップ。7年前に、当時働いていた会社がDELLに買収されたときに個人用として各従業員がタダで貰った。Core 2 Duo T7500 2.2GHz の CPU でメモリは 4GB、160GB の HDD。

Windows Vista(Business、32bit)と言うWindows8ほどではないものの最悪に近いOSであることと画面が1280x800と少々小さめであることを除けば、最近のMacほどはないものの、ウェッジ型の薄く見える形状で気に入っている。毎年のバケーションにもいろいろな国に持って行っており、バッテリーは3代目だ。

気に入っているとは言え、このラップトップは、1年以上使用されているすべてのPCに共通する問題を抱えている。

お・そ・い
今年は家族メンバーのPCのアップグレードが2件予定されており(1件は実施済み)、新しいラップトップに買い換える予算がない。

そこで、最小限の費用での延命策を検討した結果、採用したのが以下の2項目。
  • WiFi の 802.11g から 802.11n への変更
  • HDDをSSDに換装
WiFi の変更は、手元に小型の802.11n 小型USBドングルがあったので試しに入れてみた。あまり期待はしていなかったのだが、実際に体感できる速度の向上(30~40%?)があったのは儲けもの。単価$10前後で実施できる。本当は内臓の WiFi が交換できれば、USB端子も消費せずに済むのだが、ないものねだりをしても仕方がない。

ドングルを挿して、付属のドライバをインストールする。コントロールパネルから内臓の WiFi を禁止してお終い。あ、MACアドレスで固定のDHCPを行っている場合は、当然DHCPサーバのMACアドレスを変更しなければならない。

ただし、ドングルにもいろいろあるようで、最初はRaspberry Pi を買った時に付属してきた(Linuxでサポートされていない、したがって役に立たない)Realtek RTL8188CU を使っていたが、どうも不安定で、20分ごとにデバイスが再起動していた。Raspberry Piで実績のあったEdimaxに変更したら随分安定になった。

インターネットに使用しているケーブルモデムは、最近スピードサイトで測ったら60Mbps程度。家の中のLANも100Mbpsから1Gbpsに順次交換している。WiFiも速くすると効果的と判った。

HDDからSSDへの換装は、依然SSDで否定的な経験をしたので躊躇していたが、もうそろそろ時期と思い、再び実践。結果は
は・や・い
の一言。まるで購入時のあのサクサクさが戻ってきたようだ。

使用したSSDは SanDisk の 256GB。WDの普及版1TB HDD と比べるとバイトあたり単価は約8倍。
  • SSD 256GB $120
  • HDD  1TB $60
将来はこの価格差が縮む可能性はあるか?

SSDの容量は内部チップの面積(数)に正比例し、これが価格の大部分を占めるが、HDDでは、プラッタを除く、ハウジングやアクチュエータ、ボイスコイル、PC基盤といった主要部品は容量にあまり依存しないので、容量と価格は正比例しないと思う。だから、単純な価格比にはならないだろう。

HDDからSSDへの換装は、マザーボードに空きSATAコネクタが2個あるLinuxを使うと至極簡単。

まず、HDDより少し大きめの容量のSSDを買って来る。我が家の場合は160GB -> 256GBとして、SanDisk のUltra Plus にした。

データのバックアップは言われなくてもちゃんと取ること。小生はGenie9というWindowsのバックグラウンド型バックアッププログラムを使っているので、新しいファイルシステムに変更があると即座にその分がバックアップされるようになっている。

ラップトップをシャットダウン(「スリープ」はだめ)して、バッテリを取り去り、HDDを外す。Linux マシンにHDDとSSDを装着して起動。以下のコマンドを実行して数十分待てばディスクの複製が完了(HDDが/dev/sdb、SSDが/dev/sdcの場合)。
[root@linux ~]# dd if=/dev/sdb of=/dev/sdc bs=16M

HDDのあったところにSSDを装着して蓋を閉め、バッテリを戻してラップトップを起動すると、もしかしたらBIOSが何か言ってくるかもしれないが、すべて肯定的に返事をすれば、きっと立ち上がり時間が1/10になっていることに驚くはず。

元のHDDより大容量のSDDを使ったので、ディスクの後ろの方が余る。小生が実践した換装では、86GBほど余ってしまった。WindowsでCドライブしか使っていなければ、新たなパーティションを作ってDドライブとして使うのが一番簡単。小生の場合はちょっと複雑で、Cの後ろにバックアップの対象としないVMWareの仮想ドライブファイルを格納するVドライブが既にある(バックアップはVMWareのゲストOS内で実行)。新たなパーティションでやたらドライブ数を増やしても仕方がないので、この新しいパーティションはVドライブをコピーしてきて、以前のVドライブの場所はCドライブを延長しようかと考えている。ま、この辺は各自でどうぞ。

これで7年前のラップトップが快調に甦った。あと3年ぐらいは使えそうな感じがする。

大抵の突然のわけの分からない不具合はSELINUXを禁止すると治る

今までに何回わけの分からない不具合がこれだったか…。

ほとんどの場合は、POSIXのファイルパーミッションでは不可思議な現象に関連していたが、今回はFedora 20で新しいサーバを構築中に起こった。

下は yum  実行時に起きたわけの分からないエラーメッセージ。リポジトリサーバがダウンしていたのかと思い半日待ったが埒があかない。「まさか」と思いつつ /etc/selinux/config で「SELINUX=disabled」にしたらあっけなく治った。

[root@mill3 ~]# yum makecache
Loaded plugins: langpacks, refresh-packagekit


 One of the configured repositories failed (Unknown),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Disable the repository, so yum won't use it by default. Yum will then
        just ignore the repository until you permanently enable it again or use
        --enablerepo for temporary usage:

            yum-config-manager --disable <repoid>

     4. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot retrieve metalink for repository: fedora/20/x86_64. Please verify its path and try again

SELINUX は本当に質(たち)が悪い。

2014年5月10日

Fedora 20: em1 ではなく eth0 にしたい

我が家のサーバ群は4年前に構築した Fedora 13(以下FC13)。最近のOpenSSLのセキュリティホールなどの記事を読むに連れ、そろそろ更新の時期と考え、まずはセキュリティに一番関係するファイアウォールのアップグレードから始めた。32ビットから64ビットへの移行も大きな動機。
 
選んだのは現在最新のFC20。世の中はUbuntu系が急速に普及しているが、Ubuntu系は経験的にワークステーションにはよくても、systemd採用以前のバージョンはいろいろなサービスの直交性が低い印象があり、また今まで延々とFedoraで作ってきたいろいろな自家製サービスやツールを考えると、ここ暫くはFedora系に固執するのが安全という判断。

幸いなことに、あのWindows8もどきの最悪なデスクトップ(Gnome3)を嫌う多くの人に支持されたGnome2の直径子孫のMATEのスピンがあるのでそれを使うことにした。

前置きが長くなったが、取りあえず古いPC上に実験的にMATEをインストールする。インストーラのanacondaが使いにくくなったなど色々あるが、それらは別稿で書くとして、一番驚いたのは、ネットワーク・デバイス名が「ethX」から「emY」に変更されていること。ifconfigの出力フォーマットの変更(こちらの方が影響の可能性が大きそう)もさることながら、実害の可能性は低いと思うが、もしかしたら自家製のツールのもうとっくに忘れた部分でわけの分からない壊れ方をするかもしれない。

[root@mill3 ~]# ifconfig
em1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::6670:2ff:fe11:29eb  prefixlen 64  scopeid 0x20<link>
        ether 64:70:02:11:29:eb  txqueuelen 1000  (Ethernet)
        RX packets 139  bytes 21434 (20.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ぐぐってみると、どうもこの仕様はFC15あたりから導入されたらしいが、「emY から ethX に戻したい」と言う同じ悩みを抱えた人は大勢いるらしく、結構な数の記事がヒットする。それらを色々試してみるがうまく行かない。結局たどり着いたのはこちらの記事

これによると、以下の2ヶ所を手当てすればよい。
  • grub の設定ファイルのカーネルへの引数
  • /etc/sysconfig/network-scripts/ifcfg-eth* の作成
  • udev のルールファイルを /etc/udev/rules.d/60-net.rules でオーバライド
他の様々な記事では、udev のルールファイルを変更するとよいと書いてあるが、ルールファイルを変更(と言うよりオーバライド)しただけでは何も変化はなかった。

まず、カーネルのブート時にemYへのリネームを禁止する引数を渡す。

/boot/grub/grub.conf と言うgrub独自言語のファイルが /boot/grub2/grub.cfg と言うシェルスクリプトに変わってしまったことにも驚いたが、とにかく集めた情報を基に、以下のパラメタ(net.ifnames=0 biosdevname=0)をカーネルの起動時コマンドラインに追加する。

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Fedora (3.14.2-200.fc20.x86_64) 20 (Heisenbug)' --class fedora --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-3.11.10-301.fc20.x86_64-advanced-4964450e-bb98-4b4e-ac6f-cfd3c0f272c6' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_gpt
        insmod part_gpt
        insmod diskfilter
        insmod mdraid1x
        insmod ext2
        set root='mduuid/2978f1951a5f27f2fa616dc44e7225c6'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint='mduuid/2978f1951a5f27f2fa616dc44e7225c6'  4dd4ee0a-f0ce-48a1-894d-e329ee6ac3da
        else
          search --no-floppy --fs-uuid --set=root 4dd4ee0a-f0ce-48a1-894d-e329ee6ac3da
        fi
        linux   /vmlinuz-3.14.2-200.fc20.x86_64 root=UUID=4964450e-bb98-4b4e-ac6f-cfd3c0f272c6 ro rd.md.uuid=2978f195:1a5f27f2:fa616dc4:4e7225c6 rd.md.uuid=f52a49f7:ae3bca96:5f1530ab:cd3bd27c rd.md.uuid=d085c9c0:4d36caf6:ec19a007:ad1e1c74 vconsole.font=latarcyrheb-sun16  rhgb quiet LANG=en_US.UTF-8 net.ifnames=0 biosdevname=0
        initrd /initramfs-3.14.2-200.fc20.x86_64.img
}
以下略


上記記事によれば、FC18までは「biosdevname=0」だけでよかったが、FC19以降ではこれだけだと以下のようなドライバの付けたデバイス名になってしまう。

[root@mill3 ~]# ifconfig
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::6670:2ff:fe11:29eb  prefixlen 64  scopeid 0x20<link>
        ether 64:70:02:11:29:eb  txqueuelen 1000  (Ethernet)
        RX packets 139  bytes 21434 (20.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

/boot/grub2/grub.cfg は新しいカーネルがインストールされる度に書き換えられてしまうので、この変更を将来も自動的に行うためには、/etc/default/grub にこれらを追加しておく。

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.md.uuid=2978f195:1a5f27f2:fa616dc4:4e7225c6 rd.md.uuid=f52a49f7:ae3bca96:5f1530ab:cd3bd27c rd.md.uuid=d085c9c0:4d36caf6:ec19a007:ad1e1c74 vconsole.font=latarcyrheb-sun16 $([ -x /usr/sbin/rhcrashkernel-param ] && /usr/sbin/rhcrashkernel-param || :) rhgb quiet
net.ifnames=0 biosdevname=0"
GRUB_DISABLE_RECOVERY="true"

または、/etc/default/grub を変更しておいて「grub2-mkconfig -o /boot/grub2/grub.cfg」を実行しても同じこと。

Fedora のインストール時には /etc/sysconfig/network-scripts/ifcfg-em* と言うシェルスクリプトのインクルードファイルが各々のネットワークインタフェース用に作成される。これがないと ifup とか ifdown が動かない。ifcfg-em* を ifcfg-eth* にリネームして、内容の「NAME=emY」を「NAME=ethX」に変更する。

後はリブートしてやれば、下のように目出度く馴染みの「ethX」 になっているはず。

[root@mill3 ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::6670:2ff:fe11:29eb  prefixlen 64  scopeid 0x20<link>
        ether 64:70:02:11:29:eb  txqueuelen 1000  (Ethernet)
        RX packets 20  bytes 3596 (3.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ネットワークインタフェースが一つだけならこれでお終いでもよいが、我が家のファイアウォール・ゲートウェイのように複数のインタフェースがある場合は、 それぞれのインタフェースに決定的な名前を付けたい。そのためには udev のルールファイルを使う。

最近のLinuxのディストリビューションでは、/usr/lib にディストリビューションのデフォルト設定ファイルを置き、ローカルの設定変更は /etcの下の同名のファイルでオーバライドするようになっている。Fedora 20 のネットワークインタフェースの udev の場合は、既にデフォルトファイルとして /usr/lib/udev/rules.d/60-net.rules があるので、以下のような /etc/udev/rules.d/60-net.rules を作ってオーバライドする。

[root@mill3 ~]# cat /etc/udev/rules.d/60-net.rules
# PCI device 0x1011:0x0019 (tulip)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:c0:f0:4c:f5:78", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="60:a4:4c:b5:26:48", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

と言うのは、udev のマニュアルページに書かれていることだが、 実際は違うようだ。この方法を実践してみたが、どうも eth0eth1 の割り付けが不安定で、ブートの度にひっくり返ることがある。そこで、/etc/udev/rules.d の方を 61-net.rules に改名したら安定したように見える。マニュアルページの記載とは異なり、/etc/usr/lib 間の優先度の違いはないように見える。優先したい方(/etc 側)を文字列的に後になるような名前にした方が無難のようだ。

一部のサーバ群の管理では「emY」の方が論理的・仮想的で便利だという意見もあり、それがこの「ethX」から「emY」への変更の理由なのだろうが、過去との互換性の面では困った「新しもの」だ。エイリアスを許せるようにだとかできないのだろうか?