2

Below is a kernel module which can be compiled and run nicely. I have written a method show which gets the pointer to a hashtable and prints it. But if I use the methods argument, b, I get a compilation error. I can only use the global variable a.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/hashtable.h>

MODULE_LICENSE("GPL");

typedef struct {
    int age;
    struct hlist_node my_next;
} my_type;

DEFINE_HASHTABLE(a, 3);
my_type *node1, *node2, *node3;

void show(struct hlist_head b[]){
    int i;
    my_type *temp;

    printk(KERN_INFO "a: %p \tb: %p \n", a, b);    // Always the same address.

    hash_for_each(a, i, temp, my_next){           // Change the a to b
        printk(KERN_INFO "%d\n", temp->age);
    }
}


int init_module(void){
    printk(KERN_INFO "Hi.\n");

    node1 = kmalloc(sizeof(my_type), GFP_KERNEL);
    node1->age = 28;
    node2 = kmalloc(sizeof(my_type), GFP_KERNEL);
    node2->age = 27;
    node3 = kmalloc(sizeof(my_type), GFP_KERNEL);
    node3->age = 20;

    show(a);
    hash_add(a, &node1->my_next, 0);
    hash_add(a, &node2->my_next, 1);
    hash_add(a, &node3->my_next, 1);
    show(a);

    return 0;
}


void cleanup_module(void){
    kfree(node1);
    kfree(node2);
    kfree(node);
    printk(KERN_INFO "Bye.\n");
}

The error I get is:

In file included from include/linux/thread_info.h:11:0,
             from /usr/src/kernels/3.15.8-200.fc20.x86_64/arch/x86/include/asm/preempt.h:6,
             from include/linux/preempt.h:18,
             from include/linux/spinlock.h:50,
             from include/linux/seqlock.h:35,
             from include/linux/time.h:5,
             from include/linux/stat.h:18,
             from include/linux/module.h:10,
             from /home/k/development/hash2/main.c:1:
/home/k/development/hash2/main.c: In function ‘show’:
include/linux/bug.h:33:45: error: negative width in bit-field ‘<anonymous>’
 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
                                         ^

I have tried playing with the definitions like using struct hlist_head * b[] and using in the hash_for_each macro the *b but non worked.
I also tried defining DEFINE_HASHTABLE(c, 3); inside the method show() as shown below works, but it's quite useless.

void show(struct hlist_head b[]){
    int i;
    my_type *temp;

    DEFINE_HASHTABLE(c, 3);
    printk(KERN_INFO "a: %p \tb: %p \n", a, b);

    hash_for_each(c, i, temp, my_next){
        printk(KERN_INFO "%d\n", temp->age);
    }
}

So, why do I get this error? How do I solve it?

Ramzi Khahil
  • 4,932
  • 4
  • 35
  • 69
  • Looks like a problem with the way the macros are defined - you may have to make `show` a macro to work around this. – Paul R Aug 17 '14 at 09:50

1 Answers1

2

hash_for_each is a macro which in turn uses another macro (ARRAY_SIZE) to determine the size of the array passed to hash_for_each as first parameter.

You pass a pointer to hash_for_each as 1st parameter, this makes ARRAY_SIZE choke, as "pointers are not arrays".

To get aorund this, you might like to take the approach proposed by Paul R in his comment to your question, that is implementing show() as a macro as well.

The compilation error you observe is by intention, to keep you from using code not doing what it was intended to do. The error message itself

error: negative width in bit-field ...

however is heavily missleading.

Community
  • 1
  • 1
alk
  • 69,737
  • 10
  • 105
  • 255