普段使っているユーザーでLinuxデスクトップにログインできなくなった。正しいパスワードを入力すると画面が1秒程度切り変わるけど、すぐディスプレイマネージャのログイン画面に戻ってしまう状態だった。
エラーの内容を調べる
rootではログインできたので、Ctl+Alt+F4
などでディスプレイマネージャからコンソールに切り替えて、ログインできなくなった原因を調べる。問題のユーザーはsystemd-homedでLUKSイメージを使った環境だったので、activateしてみるとI/Oエラーが出力された。
# homectl activate lufia [ 152.810994] loop0: detected capacity change from 0 to 764010613 [ 152.812280] blk_update_request: I/O error, dev loop0, sector 764010608 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0 [ 152.812446] blk_update_request: I/O error, dev loop0, sector 764010608 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 152.812554] Buffer I/O error on dev loop0, logical block 95501326, async page read [ 152.813969] blk_update_request: I/O error, dev loop0, sector 764010608 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 152.814210] Buffer I/O error on dev loop0, logical block 95501326, async page read [ 152.815182] blk_update_request: I/O error, dev loop0, sector 764010608 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 152.815344] Buffer I/O error on dev loop0, logical block 95501326, async page read [ 153.564587] device-mapper: table: 254:0: len=763977845 not aligned to h/w logical block size 4096 of loop0 [ 153.564591] device-mapper: core: Cannot calculate initial queue limits [ 153.564716] device-mapper: ioctl: unable to set up device queue for new table. [ 153.568854] blk_update_request: I/O error, dev loop0, sector 764010608 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 [ 153.569169] Buffer I/O error on dev loop0, logical block 95501326, async page read
ここで
blk_update_request: I/O error, dev loop0, sector xxx
という嫌なエラーがみえる。また、homectl inspect
やhomectl list
などで現在の状態を調べると、dirtyという状態になっていることがわかる。systemd-homedはdeactivateせず終了したとき、dirty状態になるらしい*1。
# homectl list NAME UID GID STATE REALNAME HOME SHELL lufia 60331 60331 dirty lufia /home/lufia /bin/bash 1 home areas listed.
このフラグは、/home/[user].homeにあるLUKSイメージにhome-dirty=1
として属性が付けられている。属性を消せばinactive状態に戻る。
# attr -l /home/lufia.home Attribute "home-dirty" has a 1 byte value for /home/lufia.home # attr -r /home/lufia.home home-dirty
systemd-homedのLUKSストレージ構造
systemd-homedはディレクトリやCIFSサーバなどにストレージを切り替えられるようになっていて、LUKS+Btrfsなファイルシステムイメージがデフォルトとして使われる。この場合、以下の要素が使われる。
LUKSストレージでユーザーが作られると、ユーザーのホームディレクトリは/home/[user].homeという名前のイメージファイルで管理されるようになる。イメージファイルはそのままではマウントできないので、device-mapperでイメージをloopデバイスにする。このデバイスは、LUKSで暗号化したうえでBtrfsファイルシステムとしてフォーマットされる。こうして作られたファイルシステムはログインするとsystemd-homedによって/home/[user]へマウントされるので、ユーザーのデータは最終的に[user].homeのイメージファイルへ書かれることになる。
データを取り出す
ローカルには紛失すると困るものはないはずだが、作業中のソースコードなどは救出したいので必要なデータを取り出した。systemd-homed - ArchWikiにレスキューコマンドがあったのでそのまま使う。
# losetup -fP lufia.home # cryptsetup open /dev/loop0p1 rescue # mount /dev/mapper/rescue /mnt/
これで/mnt/[user]からファイルを参照できるようになるので、あとはtarなどで必要なファイルをコピーする。それが終わったら新しくユーザーを作って、逃がしておいたファイルを戻せばよい。ここでは、新しいユーザーはLUKSイメージを使わないストレージにした。
# userctl create --storage=directory --uid=60331 --member-of=wheel lufia
暗号化はディスク全体でやればいいし、Btrfsディスクイメージの利点もあまり感じていなかった。
コマンドとsystemd-homedの違い(未解決)
レスキュー用のコマンドではマウントできるのに、systemd-homedではactivateできないところが不思議だったのでjournalctlでログを読む。
# journalctl -u systemd-homed --since=today Jan 03 10:49:54 plage systemd-homed[359]: lufia: changing state inactive → activating Jan 03 10:49:54 plage systemd-homework[506]: Provided password unlocks user record. Jan 03 10:49:54 plage systemd-homework[506]: Successfully locked image file '/home/lufia.home'. Jan 03 10:49:54 plage systemd-homework[506]: Backing file is fully allocated already. Jan 03 10:49:54 plage systemd-homework[506]: Setting up loopback device /dev/loop0 completed. Jan 03 10:49:55 plage systemd-homework[506]: device-mapper: reload ioctl on home-lufia (254:0) failed: Invalid argument Jan 03 10:49:55 plage systemd-homework[506]: Failed to unlock LUKS superblock: No such device Jan 03 10:49:55 plage systemd-homed[359]: block device /sys/devices/virtual/block/loop0 has been removed. Jan 03 10:49:55 plage systemd-homed[359]: Activation failed: No such device Jan 03 10:49:55 plage systemd-homed[359]: lufia: changing state activating → inactive
ここで、
block device /sys/devices/virtual/block/loop0 has been removed. Activation failed: No such device
とあるのは、systemd-homedの処理途中でエラーが発生した場合にloopデバイスが残らないように削除しているだけなので問題ではない。なのでおそらく
device-mapper: reload ioctl on home-lufia (254:0) failed: Invalid argument
が、レスキュー用のコマンドとの差異だろう。次の行に出力されたログから、
のどこかでioctlがエラーになっているのだと思うが、簡単には追えそうになかったので諦めた。
参考情報
調べているときに参考になった記事。