Buddy_Zhang1 发表于 2016-04-18 10:31

调试两天无法解决的问题,各位大神帮一下忙

问题是我在创建一个 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 之后就对该指针进行操作,就导致系统崩溃.

这个问题该如何解释,请大神给建议.

nswcfd 发表于 2016-04-18 11:36

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);
}

Buddy_Zhang1 发表于 2016-04-18 15:37

回复 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


特别感谢您

nswcfd 发表于 2016-04-22 10:21

hehe,不用客气。
页: [1]
查看完整版本: 调试两天无法解决的问题,各位大神帮一下忙