2008/05/10

Ubuntu 8.04 ハイバネート(hibernate)異常2

前回の修正にて正常動作するに見えたが、まれにハイバネート異常が再発した。

再度調査にて、カーネルドキュメントの以下解説を確認した。

FileName:/usr/src/linux-source-2.6.24/Documentation/power/swsusp.txt

  If you want to limit the suspend image size to N bytes, do
  echo N > /sys/power/image_size
  before suspend (it is limited to 500 MB by default).

サスペンドイメージの上限サイズを変更するなら、/sys/power/image_sizeにそのサイズ(バイト)
を書き込めと書いてある。(デフォルトの上限は500MB)

さらに後ろに読み進めると、以下の記述があった。

  If you set it to 0 (eg. by echo 0 > /sys/power/image_size as
  root), the 2.6.15 behavior should be restored. If it is still too
  slow,

/sys/power/image_sizeに0を書き込めば必ず動作するが、動作は遅いと書いてある。

必ず動作することの方が重要であるため、ハイバネートの際には/sys/power/image_sizeに0を書き込むこととする。

また、ハイバネートからの復帰時に非常に動作が遅くなる現象を経験したことがあり、その解決策を探したところ、以下の記述があった。

  Q: After resuming, system is paging heavily, leading to very bad interactivity.
  A: Try running
    cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null
    after resume. swapoff -a; swapon -a may also be useful.

ハイバネートからの復帰時に動作が遅くなる現象は、ページング処理の頻発が原因であることを確認している。
(実際、swapoff -a ;swapon -a にて記述どおり改善した経験がある)

cat .... >/dev/null の記述は試したことがないため、記述どおり動作させてみたところ、/dev/zero の読み込みを行うらしく、無限ループに至り正しく動作しなかった。

記述の内容は /proc/..../maps から抽出できるオープン中のファイルのファイル名より、ファイルの再読み込みを行うことで、ページングの優先度を下げ、動作不良に至らない様にすると解釈した。
同手順は良い手順だが、無限ループに陥る/dev/zeroの再読み込みを省略させる必要があるため、抽出されるファイル名より、/dev/を含むものを省略する以下手順に変更することとした。

  (cat /proc/[0-9]*/maps | grep / |sed 's:.* /:/:;/\/SYSV/d;/\/dev\//d' |xargs cat )>/dev/null

xargs を使用した理由は/proc/.../mapsから抽出されるファイル名のリストが、シェル関数の容量上限である1024バイトを超える場合であっても正常動作させるためである。

以上を踏まえて、以下のシェルスクリプトを追加した。

  FileName: /etc/acpi/suspend.d/00-image_size_upd.sh
  #!/bin/sh
  (cat /proc/[0-9]*/maps | grep / |sed 's:.* /:/:;/\/SYSV/d;
  /\/dev\//d;/(deleted)/d' |xargs cat )>/dev/null

  echo 0 > /sys/power/image_size

シェルスクリプトファイルには、以下コマンドにて実行権を付与している。
  (この記事を試される場合、忘れずに付与してほしい)

  chmod +x /etc/acpi/suspend.d/00-image_size_upd.sh

前回の記事でも記載漏れがあったが、GRUBのkernelの行に resume=スワップディバイスの設定を追加する必要がある。

FileName:/boot/grub/menu.lst
: :
kernel /vmlinuz-2.6.24-16-generic root=UUID=e51044c7-70dc-414e-a5f6-d75203567c08 ro quiet splash resume=/dev/sda3
: :

当方の環境ではスワップディバイスは/dev/sda3であるが、 環境によって異なる。
cat /proc/swaps でスワップディバイスを一覧できるので、不明な場合は試してもらいたい。

以上の設定で、安定したハイバネート環境となった。
カーネルドキュメントには他にも色々と参考となる記述があるため、もっと高速化が図れると考える。
今後も引き続き調査をおこなっていくこととする。

ご指摘事項など、遠慮なく行っていただければ幸いである。

Ubuntu 8.04 (Hardy Heron) のハイバネートが正常に行われるようにする
 GUIの機能について指摘を記載頂いておりました。感謝します。

2008/05/03

Ubuntu 8.04 ハイバネート異常

ハイバネート(hibernate)とは直訳すると冬眠という意味だが、コンピュータの機能におけるハイバネートとは、メモリイメージをディスクに退避して、終了(電源ダウン)する機能のことを言う。

Ubuntu 8.04+ATI Radionディスプレイドライバの環境にてハイバネートを行った場合、起動しているプログラムの数により、以下のエラーにてハイバネートが正常動作しない現象が発生した。

[ 510.945354] swsusp: Not enough free memory

調査したところ、ハイバネートでは、退避に必要なメモリサイズを/sys/power/image_sizeから参照しており、このサイズが500MB( 524288000 )固定であるため、スワップを含めたメモリ使用量が500MBを超えた場合に、上記エラーとなることが判明した。

ハイバネートの手続きは/etc/acpi/hibernate.sh 及び/etc/acpi/suspend.d/*で定義されているので、/etc/acpi/suspend.d/ディレクトリに/sys/power/image_sizeを現在のスワップを含めたメモリ使用量で更新する以下シェルスクリプトファイルを追加した。

FileName: /etc/acpi/suspend.d/00-image_size_upd.sh
#!/bin/sh
free | \
awk '{if($1=="-/+"){size+=$3;}if($1=="Swap:"){size+=$3;}}END{print size*1024}' \
> /sys/power/image_size

シェルスクリプトファイルを追加が終わったら、以下コマンドにて実行権を与えておく。
chmod +x /etc/acpi/suspend.d/00-image_size_upd.sh

以上の修正にて、ハイバネートが正常に動作するようになった。
同様の事象にて困っている方がおられたら参考にされたい。