调试两天无法解决的问题,各位大神帮一下忙
问题是我在创建一个 struct dentry 的过程中,一个 bit 设置不对引起的.源码如下: /fs/dcache.c
static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b)
{
BUG_ON(!d_unhashed(entry));
spin_lock_bucket(b);
entry->d_flags &= ~DCACHE_UNHASHED;
hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
spin_unlock_bucket(b);
}
static void _d_rehash(struct dentry * entry)
{
__d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash));
}
1. 如上面的源码所示,调用 _d_rehash() 时候,使用 d_hash() 函数获得了 dcache_hashtable 的入口,
此时,入口类型为 struct dcache_hash_bucket,此时其成员 head.first 的值为 NULL.
2. 接着调用 __d_rehash() 经常 spin_lock_bucket(b) 处理之后, head.first 的值的最低位被值位,为 0x00000001.
问题来了,由于这样的操作,导致 head.first 的不为 NULL,在接下来的处理过程中
hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
其源码如下:
static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
struct hlist_bl_head *h)
{
struct hlist_bl_node *first;
/* don't need hlist_bl_first_rcu because we're under lock */
first = hlist_bl_first(h);
n->next = first;
if (first)
first->pprev = &n->next;
n->pprev = &h->first;
/* need _rcu because we can have concurrent lock free readers */
hlist_bl_set_first_rcu(h, n);
}
如上诉,first 的值为 1,但此时判断 first 不为 NULL 之后就对该指针进行操作,就导致系统崩溃.
这个问题该如何解释,请大神给建议. hlist_bl 是不是利用ptr的最bit低位作为lock用?
那样的话,加锁就不能是spin-lock,而使用相关的hlist_bl版本(hlist_bl_lock)?
或者hlist_bl的first函数,在返回的时候应该忽略bit位。static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h)
{
return (struct hlist_bl_node *)
((unsigned long)h->first & ~LIST_BL_LOCKMASK);
} 回复 2# nswcfd
谢谢,根据您的建议,我找到问题的出错点了
static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h)
{
return (struct hlist_bl_node *)
((unsigned long)h->first & ~LIST_BL_LOCKMASK);
}
LIST_BL_LOCKMASK 的定义有两种,因为打开了 BIT_SPINLOCK 的宏,
所以 #define LIST_BL_LOCKMASK 1UL
之前定义为 :
#define LIST_BL_LOCKMASK 0UL
特别感谢您 hehe,不用客气。
页:
[1]