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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.