2020/07/05(日)NILFS使用時にLinux Kernelエラーが起こる問題の解決策

はてブ数

最近の新しいLinux KernelでNILFS(NILFS2)を使用すると、最初の書き込み時に

BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8

となるエラーの解決方法(対処療法)。

NILFSとは

ログ構造化ファイルシステムと言われる、ファイルを変更するたびに常にスナップショットを自動的に保存できるLinux標準サポートのファイルシステムです。

/home 以下などをNILFSにしておくと、間違えてファイルを書き換えたときや、間違えてファイルを削除したときに、1時間前や1週間前の状態に遡ってファイルを復元することができます。

間違ってファイルを削除(上書き)してまうこと、ファイルを直接変更してしまってから元に戻したいことは誰しもあると思いますが、NILFSならいつでも元に戻せるため人為的にミスにとても強く重宝しています。

新しいカーネルで動作不安定に

このNILFSですが、最近の(ここ1年ぐらいの)カーネルで動作不安定になる不具合があります。Debian 10.4をインストールした際にこの問題に当たってしまいました……。

調べるとカーネルのファイルキャッシュに対するちょっとした変更(パッチ)が原因となっているようです。解決策はLinux系のMLにありました(そしておそらく投稿者の記事)。

要約すると「NILFSをマウントする前に、ダミー書き込みをすれば良い」とのことです。

簡単な解決策

/etc/fstab では自動マウントせずに(noautoオプションをつける)、rc.localでマウントするように変更します。

dd if=/dev/sda6 of=/dev/sda6 count=1
mount /home

/dev/sda6 やマウント場所は該当のパーティション等に合わせてください。ddコマンドで512バイトほどダミー書き込みをしてからマウントします。たったこれだけで問題は解決します。

やや複雑な解決策

rc.local でマウントする方法では、NILFSパティーション以下にDBデータ等サービスで使用するデータを置く場合や/varがNILFSパーティションだった場合に問題があります。rc.local のタイミングでマウントするのでは遅すぎるからです。

ですので、理想としてはfstabでマウントする直前にダミー書き込みを実行したいのです。

Debian系のsystemd環境では以下のような設定ファイルを置くことで、fstab実行直前にダミー書き込みを実現できます。

# /etc/systemd/system/nilfs2-dummy-write.service
[Unit]
Description=NILFS2 dummy write
DefaultDependencies=no
After=local-fs-pre.target
Before=local-fs.target

[Service]
ExecStart=/bin/dd if=/dev/sda6 of=/dev/sda6 count=1
Type=oneshot

[Install]
WantedBy=sysinit.target

ファイル作成後、サービスとして認識されたか確認します。

# systemctl list-unit-files --type=service | grep dummy
nilfs2-dummy-write.service             disabled

認識されているようなら、サービスを有効にします。

# systemctl enable nilfs2-dummy-write
# systemctl list-unit-files --type=service | grep dummy
nilfs2-dummy-write.service             enabled

参考文献

まとめ

  • NILFS/NILFS2はとても便利なのに利用者が少ない。
  • パッチが出てるので、近々修正されるとは思う。
  • systemdの勉強になった。

2000/02/29(火)vndrv memo

はてブ数
###############################################################################
 Virtual Network Driver I/O API specification
						Ver 0.03
###############################################################################
※基本は「リニアアドレス」を使用。

2F10h	R/W
	I/O APIの存在確認
	書き込んだバイトの NOT が読み出せる。
	初期値 0
	※他のアプリで変更されている可能性があるため0を期待してはいけない。
	※よって、非 0ffh の確認は 2F12h で行うと良い。

2F12h	R/W
	API有効化レジスタ。初期値 0。
	1を設定すると有効化(有効化しない限り、これより下のAPIは無視)

2F14h	W
	コマンドレジスタ
	書き込んだ、2バイトがコマンドになる。

	B15-B08	IOH	コマンド
	B07-B00 IOL	オプション(マウントポイント番号)

###############################################################################
 Commands
###############################################################################
00h	Get Drives

	IN	IOH = 00h
	Ret	AL	マウントポイント数

1Bh	Find First

	IN	IOH = 1Bh
		IOL =    マウントポイント番号
		FS:[ESI] カレントディレクトリ
		GS:[EDI] ファイル情報バッファ
	Ret
		AX = 0	成功
		AX !=0	失敗
			 AX = 02h	ファイルが存在しない
			 AX = 03h	パスが見つからない
			 AX = 12h	これ以上ファイルが存在しない
		GS:[EDI] ファイル情報を転送

1Ch	Find Next

	IN	IOH = 1Ch
		IOL =    マウントポイント番号
		FS:[ESI] カレントディレクトリ
		GS:[EDI] ファイル情報バッファ
	Ret
		AX = 0	成功
		AX !=0	失敗
			 AX = 12h	これ以上ファイルが存在しない
		GS:[EDI] ファイル情報を転送

###############################################################################
 あると嬉しい
###############################################################################
2F18h	B
	補助コマンドレジスタ
	書き込んだ、1バイトがコマンドになる。
	8086モード、80386モードどちらからでも使用可能。

00h	Break
	IN	なし
	Ret	なし

	Tsugaruをbreakさせる(brkonのイベント発生と同じ扱い)

09h	Print String
	IN	DS:[EBX]	NULL終端文字列
	Ret	なし

	CUIコンソールに文字列を出力。

0Ah	Print Dump
	IN	DS:[EBX]	表示するメモリ位置
		ECX		バイト数
	Ret	なし

	CUIコンソールに ECXバイト(以上)をダンプ(dm)出力。

0Bh	Print Dump for Liner Address
	IN	[EBX]		表示するメモリ位置
		ECX		バイト数
	Ret	なし

0Ch	Print Dump for Physical Address
	IN	[EBX]		表示するメモリ位置
		ECX		バイト数
	Ret	なし

###############################################################################
 ファイル名の注意
###############################################################################
・文字列の終端は NULL (00h)
・ディレクトリの区切り記号は \
・DOSの8.3ファイル形式が最大長。
・大文字小文字の区別がない。
・ファイル名の文字コードは Shift-JIS(とりあえず日本語問題は無視)

###############################################################################
 ファイル情報バッファ
###############################################################################
	+00h	b	ファイル属性
	+01h	d	ファイル更新日時
	+05h	d	ファイルサイズ(byte)
	+09h	13byte	8.3形式ファイル名(NULL終端)

ファイル更新日時
	bit	31-25	year - 1980
	bit	24-21	month
	bit	20-16	day
	bit	15-11	hours (0-23)
	bit	10-5	minutes
	bit	4-0	seconds/2

ファイル属性
	Bit 7	0	Reserved
	Bit 6	0	Reserved
	Bit 5	1	アーカイブ
	Bit 4	?	ディレクトリ
	Bit 3	0	Volume
	Bit 2	0	Systemファイル
	Bit 1	?	Hidden
	Bit 0	?	Read Only

###############################################################################
Memo:
int 2fh
	1123
	110C
	111B
	111C

http://www.oldlinux.org/Linux.old/docs/interrupts/int-html/int-2f-1.htm