Re: Newbie: ENBD on kernel 2.6 - kernel crash!
"Peter T. Breuer" <[email protected]>
| Newsgroups | gmane.linux.enbd.general |
|---|---|
| Message-ID | <[email protected]> |
"Also sprach Roland Paterson-Jones:"
> My gcc is 3.4.3:
Sounds way too risky to use to me, but then if you have compiled the
kernel with it before, so be it! Make sure that you compile at -O2 or
-O1.
> The enbd.ko module seems to be crashing in the call to
> blk_queue_max_sectors()
Yes that' reasonable. It's in the first loop:
for (i = 0; i < MAX_NBD; i++) {
struct enbd_device *lo = &enbd_dev[i];
/* Pavel says ...
* The new linux 2.5 block layer implementation requires
* every gendisk to have its very own request_queue
* struct. These structs are big so we dynamically
* allocate them.
*/
struct gendisk *disk = alloc_disk(ENBD_MAXCONN);
memset (lo, 0, sizeof (*lo));
if (disk) {
lo->disk = disk;
spin_lock_init(&lo->lock);
disk->queue = blk_init_queue(do_enbd_request, &lo->lock);
if (!disk->queue) {
// .. back out
return -ENOMEM;
}
enbd_init_queue(lo, disk->queue);
}
}
> which is the first thing that enbd_init_queue
> tries to do (it doesn't reach my debug line immediately after this
> call). Is there maybe some queue stuff different in 2.6.9+ ?
Quite possibly! The call is:
static void
enbd_init_queue (struct enbd_device *lo, struct request_queue *queue)
{
// PTB - set up kernel queue struct with default methods
blk_queue_max_sectors (queue, buf_sectors); /* max per request */
...
Which appears to match the usages I see in 2.6.11:
nbd:/usr/local/src/linux-2.6.11.6/drivers/block% grep blk_queue_max_sectors *.c
DAC960.c: blk_queue_max_sectors(RequestQueue,
Controller->MaxBlocksPerCommand);
cciss.c: blk_queue_max_sectors(q, 512);
floppy.c: blk_queue_max_sectors(floppy_queue, 64);
ll_rw_blk.c: blk_queue_max_sectors(q, MAX_SECTORS);
ll_rw_blk.c: * blk_queue_max_sectors - set max sectors for a request
for this queue
ll_rw_blk.c:void blk_queue_max_sectors(request_queue_t *q, unsigned
short max_sectors)
ll_rw_blk.c:EXPORT_SYMBOL(blk_queue_max_sectors);
pktcdvd.c: blk_queue_max_sectors(q, pd->settings.size);
pktcdvd.c: blk_queue_max_sectors(q, PACKET_MAX_SECTORS);
ps2esdi.c: blk_queue_max_sectors(ps2esdi_queue, 128);
ub.c: blk_queue_max_sectors(q, UB_MAX_SECTORS);
viodasd.c: blk_queue_max_sectors(q, VIODASD_MAXSECTORS);
xd.c: blk_queue_max_sectors(xd_queue, xd_maxsectors);
nbd:/usr/local/src/linux-2.6.11.6/drivers/block%
and buf_sectors is
static int buf_sectors = ENBD_MAX_SECTORS;
and the latter constant is defined in enbd.h:
#define ENBD_MAX_SECTORS 512 /* PTB max number of 512B sectors in a buffer */
so that leaves the queue as the thing to chcke. But we know it was nonzero:
disk->queue = blk_init_queue(do_enbd_request, &lo->lock);
if (!disk->queue) {
// .. back out
return -ENOMEM;
}
enbd_init_queue(lo, disk->queue);
...
enbd_init_queue (struct enbd_device *lo, struct request_queue *queue)
{
// PTB - set up kernel queue struct with default methods
blk_queue_max_sectors (queue, buf_sectors); /* max per request */
> it_queue...
> May 17 17:16:58 localhost kernel: ENBD #5153[0]: enbd_init_queue
> RPJ: e
> nbd_init_queue 1: lo is 823d0fa0, queue is 69a93d18 ...
yes - queue nonzero.
> May 17 17:16:58 localhost kernel: Unable to handle kernel NULL pointer dereference at virtual address 000003fe
But 0x03fe is what the kernel subroutine gets.
> GF VLI
> May 17 17:16:58 localhost kernel: EFLAGS: 00210212 (2.6.9-1.667)
> May 17 17:16:58 localhost kernel: EIP is at blk_queue_max_sectors+0x2c/0x3d
About 3/4 through that subroutine in ll_rw_blk.c: But the length is
absurdly long. The subroutine is:
void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
{
if ((max_sectors << 9) < PAGE_CACHE_SIZE) {
max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
}
q->max_sectors = q->max_hw_sectors = max_sectors;
}
and I cannot believe it is anywhere but the last assignment. To me it
looks as though it has got the wrong address for q from your call. It
is possible for a compiler mismatch to cause that (passing data in wrong
registers), but it sounds quite unlikely for a C call! C++ maybe.
Anyway, try a different compiler. One that matches the one used to
compile the kernel. Are you SURE you can compile a kernel
with your compiler?
Peter