In my kernel module, firstly I wrote:
1 2 3 4 5 6 7 8 |
int alloc_device(const char *name, int number) { char name[64]; snprintf(name, sizeof(name), "worker%d", number); request_cache = kmem_cache_create(name, SECTOR_SIZE, 0, NULL, NULL); ...... } |
In centos 7, this module works fine, but after port to centos 6, this kernel module reports:
1 2 |
kmem_cache_create: duplicate cache worker0 ...... |
The key to this problme is in the implementation of kmem_cache_create() in 2.6.32 linux kernel (for centos 6):
1 2 3 4 5 6 7 8 |
struct kmem_cache * kmem_cache_create (const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { ...... cachep->ctor = ctor; cachep->name = name; ...... |
After creating a new pool, it only point to ‘name’, not strdup() a new one. But the ‘name’ in my kernel module is a temporary variable (in stack), so it considers the name is “duplicated”.
The correct code should like:
1 2 3 4 5 6 7 8 9 10 11 |
static char *names[64]; /* before calling alloc_device() */ names = kcalloc(NR_OF_DEVICE, 64, GFP_KERNEL); ...... int alloc_device(const char *name, int number) { snprintf(names[number], 64, "worker%d", number); request_cache = kmem_cache_create(names[number], SECTOR_SIZE, 0, NULL, NULL); ...... } |
But why the old kernel module did not report error in centos 7? Because in centos 7 the default memory allocator is SLUB, and in centos 6 it is SLAB. They have totally different implementation.