13 Mar, 2013

1 commit

  • Abhi noticed that we were getting a complaint from the RCU subsystem
    about access of an RCU protected list under the write side bit lock.
    This commit adds additional annotation to check both the RCU read
    lock and the write side bit lock before printing a message.

    Reported by: Abhijith Das
    Signed-off-by: Steven Whitehouse
    Tested-by: Abhijith Das
    Signed-off-by: Paul E. McKenney

    Steven Whitehouse
     

26 Apr, 2011

1 commit

  • Now that the whole dcache_hash_bucket crap is gone, go all the way and
    also remove the weird locking layering violations for locking the hash
    buckets. Add hlist_bl_lock/unlock helpers to move the locking into the
    list abstraction instead of requiring each caller to open code it.
    After all allowing for the bit locks is the whole point of these helpers
    over the plain hlist variant.

    Signed-off-by: Christoph Hellwig
    Signed-off-by: Linus Torvalds

    Christoph Hellwig
     

14 Jan, 2011

2 commits

  • __d_rehash is dereferencing an almost-NULL pointer on my ARM926.
    CONFIG_SMP=n and CONFIG_DEBUG_SPINLOCK=y.

    The faulting instruction is: strne r3, [r2, #4]
    and as can be seen from the register dump below, r2 is 0x00000001, hence
    the faulting 0x00000005 address.

    __d_rehash is essentially:

    spin_lock_bucket(b);
    entry->d_flags &= ~DCACHE_UNHASHED;
    hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
    spin_unlock_bucket(b);

    which is:

    bit_spin_lock(0, (unsigned long *)&b->head.first);
    entry->d_flags &= ~DCACHE_UNHASHED;
    hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
    __bit_spin_unlock(0, (unsigned long *)&b->head.first);

    bit_spin_lock(0, ptr) sets bit 0 of *ptr, in this case b->head.first if
    CONFIG_SMP or CONFIG_DEBUG_SPINLOCK is set:

    #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
    while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
    while (test_bit(bitnum, addr)) {
    preempt_enable();
    cpu_relax();
    preempt_disable();
    }
    }
    #endif

    So, b->head.first starts off NULL, and becomes a non-NULL (address 1).
    hlist_bl_add_head_rcu() does this:

    static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
    struct hlist_bl_head *h)
    {
    first = hlist_bl_first(h);
    n->next = first;
    if (first)
    first->pprev = &n->next;

    It is the store to first->pprev which is faulting.

    hlist_bl_first():

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

    but:
    #if defined(CONFIG_SMP)
    #define LIST_BL_LOCKMASK 1UL
    #else
    #define LIST_BL_LOCKMASK 0UL
    #endif

    So, we have one piece of code which sets bit 0 of addresses, and another
    bit of code which doesn't clear it before dereferencing the pointer if
    !CONFIG_SMP && CONFIG_DEBUG_SPINLOCK. With the patch below, I can again
    sucessfully boot the kernel on my Versatile PB/926 platform.

    Signed-off-by: Russell King

    Russell King
     
  • Po-Yu Chuang noticed that hlist_bl_set_first could
    crash on a UP system when LIST_BL_LOCKMASK is 0, because

    LIST_BL_BUG_ON(!((unsigned long)h->first & LIST_BL_LOCKMASK));

    always evaulates to true.

    Fix the expression, and also avoid a dependency between bit spinlock
    implementation and list bl code (list code shouldn't know anything
    except that bit 0 is set when adding and removing elements). Eventually
    if a good use case comes up, we might use this list to store 1 or more
    arbitrary bits of data, so it really shouldn't be tied to locking either,
    but for now they are helpful for debugging.

    Signed-off-by: Nick Piggin

    Nick Piggin
     

07 Jan, 2011

1 commit

  • Introduce a type of hlist that can support the use of the lowest bit in the
    hlist_head. This will be subsequently used to implement per-bucket bit spinlock
    for inode and dentry hashes, and may be useful in other cases such as network
    hashes.

    Reviewed-by: Paul E. McKenney
    Signed-off-by: Nick Piggin

    Nick Piggin