I'm still trying to read physical sectors, and have made progress. Thanks
for the pointers on set_blocksize(), that seems to do the trick.
However, now I've got another problem. When I read blocks "too quickly", I
guess the elevator algorithm in ll_rw_block() kicks in and re-organizes my
buffer_head structures?
ReadLBA(2) - OK
ReadLBA(3) - OK
ReadLBA(4) - fails, kernel dereferences NULL,
All calls to getblk() succeed, and none of my buffer heads are NULL. I pass
this array to ll_rw_block(), which rewrites my array, leaving most of my
buffer_head pointers as NULL. So, I thought, that for each buffer head that
isn't NULL, maybe my next buffer head is in b_reqnext, but nope. It's NULL
too.
oops and my function are below. FWIW, this is the second version of my
function. Originally, I just looped, calling bread(dev, lba++, blocksize),
which oops in the same way. Both IA-32 and IA-64, kernel 2.4.0-test9.
TIA for your help.
-Matt
Unable to handle kernel NULL pointer dereference at virtual address 00000000
00000000
*pde = 37b11001
Oops: 0000
CPU: 0
EIP: 0010:[<00000000>]
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010202
eax: 00000000 ebx: c211dba0 ecx: 00000000 edx: c029bfa8
esi: 00000000 edi: 00000001 ebp: 0000001f esp: c029bf60
ds: 0018 es: 0018 ss: 0018
Process swapper (pid: 0, stackpage=c029b000)
Stack: c010d4c0 0000001f 00000000 c029bfa8 c029bfa8 c02d8be0 0000001f
c211dba0
c010d6c1 0000001f c029bfa8 c211dba0 00000000 c029a000 c0109bf0
c029a000
ffffe000 c010bbf8 c029a000 c029a000 00000000 c0109bf0 c029a000
ffffe000
Call Trace: [<c010d4c0>] [<c010d6c1>] [<c0109bf0>] [<c010bbf8>] [<c0109bf0>]
[<c0100018>] [<c0109c1e>]
[<c0109ca2>] [<c0105000>] [<c01001d0>]
Code: Bad EIP value.
>>EIP; 00000000 Before first symbol
Trace; c010d4c0 <handle_IRQ_event+60/90>
Trace; c010d6c1 <do_IRQ+a1/100>
Trace; c0109bf0 <default_idle+0/40>
Trace; c010bbf8 <ret_from_intr+0/20>
Trace; c0109bf0 <default_idle+0/40>
Trace; c0100018 <startup_32+18/cc>
Trace; c0109c1e <default_idle+2e/40>
Trace; c0109ca2 <cpu_idle+52/70>
Trace; c0105000 <empty_bad_page+0/1000>
Trace; c01001d0 <L6+0/2>
Aiee, killing interrupt handler
Kernel panic: Attempted to kill the idle task!
struct buffer_head ** my_bread(kdev_t dev, u64 lba, u64 blockstoread)
{
struct buffer_head **bh, *thisbh;
unsigned int blocksize = get_hardblocksize(dev);
unsigned int i;
if (!blocksize) blocksize = 512;
printk(KERN_INFO "about to getblk %d blocks\n", blockstoread);
bh = kmalloc(GFP_KERNEL, blockstoread * sizeof(struct buffer_head *));
if (!bh) return NULL;
for (i=0; i<blockstoread; i++) {
bh[i] = getblk(dev, lba+i, blocksize);
if (!bh[i]) {
printk(KERN_WARNING, "getblk(lba=%x) failed.\n", lba);
}
}
/* at this point, none of the bh[i]s are NULL. */
ll_rw_block(READ, blockstoread, bh);
/* now, all but the first 3 bh[i]s are NULL, and all bh[i]->b_reqnext ==
NULL */
/* Walk the chain */
for (i=0; i<blockstoread; i++) {
if (!bh[i]) continue;
thisbh = bh[i];
do {
wait_on_buffer(thisbh);
if (!buffer_uptodate(thisbh)) {
printk(KERN_WARNING "bh is not uptodate after waiting!\n");
}
thisbh = thisbh->b_reqnext;
if (thisbh) printk(KERN_INFO "my_bread walking the chain...\n");
} while (thisbh);
}
return bh;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Oct 07 2000 - 21:00:18 EST