操作系统: 08 2010存档
从panic的信息看,是在dcache_readdir的时候,就是从cache里读各inode的时候遇到麻烦了。
kernel本身是很坚固的,肯定是我的module某个地方把cache里的东西弄坏了,想想我确实有遍历目录的操作:
内核模块里自己做了一个简化版的 find_get_page:
struct
page * my_get_page(struct address_space *mapping, unsigned long
offset)
{
struct page *page;
read_lock_irq(&mapping->tree_lock);
page =
radix_tree_lookup(&mapping->page_tree, offset);
read_unlock_irq(&mapping->tree_lock);
return
page;
}
代码是从2.6.18的内核里抄来的。
在2.6.9内核的xen虚拟机上测试,现象很诡异:服务器的ssh连接突然断开,只能重连,重连后看见模块被自动卸载掉了。仔细看代码,才发现2.6.9内核的struct address_space里的tree_lock是spinlock_t,而不是rwlock_t,结果我的代码就是对着一个spinlock_t调用read_lock_irq,锁操作不对,然后又发生了什么呢?
read_lock_irq 调用了 _raw_read_lock:
static inline void _raw_read_lock(rwlock_t
*rw)
{
#ifdef CONFIG_DEBUG_SPINLOCK
BUG_ON(rw->magic !=
RWLOCK_MAGIC);
#endif
__build_read_lock(rw, "__read_lock_failed");
}
喔,kernel会判断锁的magic number,不对的话会调用BUG_ON(),进而调用BUG(),所以机器打了个嗝。
如果没有这个magic number的检测,一旦死机,错误就更难找了,这个检测虽然很土,但很体贴,也很有效。