MIRACLE
メールサービス申込 ユーザー登録 パートナー情報
お問い合わせ FAQ サイトマップ
MIRACLE LINUXの特長 製品紹介 サービス案内 購入 サポート 技術フォーラム

« Fedora Directory Serverのビルド | メイン | カーネルの勉強方法 »

2006年7月12日 (水)

ダンプ内のSPINLOCK

あるカーネルダンプのスタックが次のようになっているとします。

-----
#2 [f7fedde0] call_usermodehelper at c0130dc4
    [RA: c01c0a37  SP: f7fedde4  FP: f7fede7c  SIZE: 156]
    f7fedde4: f66a3d80  c011e39b  00000001  f7b8bc6c
    f7feddf4: f7ed4010  c0130cb6  f7fede2c  f7ed4000
    f7fede04: 00000000  00000000  00000000  00000001
    f7fede14: dead4ead  4b87ad6e  00000000  00000000
    f7fede24: 00000000  f7fff080  f7fede4c  c0327c80
    f7fede34: f7fede90  f66a3d80  00000000  00000000
    f7fede44: 00000000  ffffffff  00000000  00000001
    f7fede54: dead4ead  f7feddbc  f7feddbc  f72ad819
    f7fede64: c03430c0  c01c2d63  c03430b0  f66a3d80
    f7fede74: f72ad83c  c03430c0  c01c0a37
-------------

これは先日の説明したcall_usermodehelper()のスタックです。
上のスタック中に気になる数値 "dead4ead"が出てきます。

気になったときは、とりあえずカーネルソースをgrepです。
--------
asm-i386/spinlock.h:# SPINLOCK_MAGIC             0xdead4ead
asm-x86_64/spinlock.h:#define SPINLOCK_MAGIC  0xdead4ead
--------

どうやらspinlockに関連する数値のようです。
そこで、kernel/include/asm-i386/spinlock.hを覗いてみます。
----------
typedef struct {
       volatile unsigned int lock;
#ifdef  CONFIG_DEBUG_SPINLOCK
       unsinged magic;
#endif
}
#define SPINLOCK_MAGIC  0xdead4ead

#ifdef CONFIG_DEBUG_SPINLOCK
#define SPINLOCK_MAGIC_INIT    , SPINLOCK_MAGIC
#else
#define  SPINLOCK_MAGIC_INIT  /* */
#endif

#define SPIN_LOCK_UNLOCKED (spinlock_t) {1 SPINLOCK_MAGIC_INIT }
#define spin_lock_init(x)    do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
------------

以上の定義になっています。

SPIN_LOCK_UNLOCKEDを分解すると、
#define SPIN_LOCK_UNLOCKED (spinlock_t) {1 , SPINLOCK_MAGIC(0xdead4ead)}
となります。

さらにスピンロックを初期化するspin_lock_init()は、次のように定義されています。

#define spin_lock_init(x)    do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)

つまり、カーネルでCONFIG_DEBUG_SPINLOCKが定義されているとき、スピンロックで使われるspinlock_tの構造体は、(1, dead4ead)という数値で初期化されることがわかります。

したがって、カーネルダンプ中にdead4eadという数値が出てくれば、そこは初期化されたスピンロックを表す変数のメモリ領域であることがわかります。
このdead4eadという数値は、OS稼動中に変更されることはありませんので、ダンプファイルを見る際に、そこにスピンロックの構造があることにすぐ気づくようになります。

何か探し物をする手がかりになると思いますので、dead4eadをキーワードとして覚えておきましょう。

もちろんMIRACLE V4.0のカーネルはCONFIG_DEBUG_SPINLOCKがONになっていますので、ダンプを調査する際の大きな手がかりとなります。

みなさんもカーネルダンプ内をdead4eadで探し回って見てはいかがでしょうか。

トラックバック

このページのトラックバックURL:
http://www.typepad.jp/t/trackback/4447/5836990

このページへのトラックバック一覧 ダンプ内のSPINLOCK:

コメント

質問です。dead4eadがあると、spinlock()でシステムがハングしているという兆候になるのでしょうか?
dead4eadが見つかってから、それをどう解釈するか、どーゆー問題があるのか、みたいな解剖の方法についての解説を期待しています。

spinlock_tは
typedef struct {
volatile unsigned int lock;
unsinged magic;
}
という形式なので、メモリ上では、
f7fede10: 00000001 <-- ロックの値
f7fede14: dead4ead <-- マジックナンバー
となります。

ロック値は、初期値が1で、誰かがspinlock()に成功すると0になるため、マジック番号の直前のアドレスの値を見ると、誰かがロックを取っているかどうかは分かります。
ただ、それがデッドロックの検出にすぐに役立つわけではないと思います。

spinlockの実装については、ひらメソッドのここら辺が良いかと思います。

http://hira.main.jp/wiki/pukiwiki.php?_raw_spin_lock%28%29%2Flinux2.6

MIRACLE LINUX V4.0 ではなく 2.6.16.18 を見ていると

#ifdef CONFIG_DEBUG_SPINLOCK
# define SPIN_LOCK_UNLOCKED \
(spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \
.magic = SPINLOCK_MAGIC, \
.owner = SPINLOCK_OWNER_INIT, \
.owner_cpu = -1 }

かつ

static inline void debug_spin_lock_after(spinlock_t *lock)
{
lock->owner_cpu = raw_smp_processor_id();
lock->owner = current;
}

となっています。
なもんで、マジックナンバーの直後を見ればロックを掴んでるタスクが特定できるので、デッドロックを探す頼りにはなります。
しかし、コストの高いロックになっちゃってますね。

http://blog.miraclelinux.com/ctd/2006/06/post_05f1.html に書いとくべきでした。

カーネルの障害の2大パターンはクラッシュとハングだとすると、クラッシュの方はクラッシュダンプから地道にバグを解析するわけですが、ハングの場合は、誰がロックを握っているかわかれば道半ばというか8合目位までは到着しちゃったようなものではないでしょうか?その意味でこのマジックナンバーからハングの原因を特定できるというのはすごいヒントだと思います。

コメントを投稿

コメントは記事の投稿者が承認するまで表示されません。

会社情報 採用情報 個人情報保護方針 商標等取り扱い事項 English
Copyright(c)2000-2006 MIRACLE LINUX CORPORATION. All Rights Reserved.