2002-10-10 22:48:58

by Cliff White

[permalink] [raw]
Subject: 2.5.41 - kernel NULL pointer


System is 2-CPU PIII
Attempting to start the SAP DB. Get this msg:
SAP cannot open the sys devspace (which is on filesystem)
DB setup does include one raw partition.
Further details upon request
cliffw

Unable to handle kernel NULL pointer dereference at virtual address 00000000
printing eip:
00000000
*pde = 00000000
Oops: 0000

CPU: 0
EIP: 0060:[<00000000>] Not tainted
EFLAGS: 00010246
eax: c04b71e0 ebx: 00000000 ecx: 00000000 edx: 00000001
esi: cf26cba8 edi: c1bc4764 ebp: c26c7f54 esp: c26c7ee0
ds: 0068 es: 0068 ss: 0068
Process dbmsrv (pid: 1422, threadinfo=c26c6000 task=c4c4e760)
Stack: c01711a9 00000000 c1bc4764 c26c7f54 00004000 00000000 00000001 c1bc4764
c26c7f54 00004000 00000000 c01e92b2 00000000 c1bc4764 c26c7f54 00004000
00000000 00000001 cee2c314 c1bc4764 00002000 c1bc4764 c1bc4784 c01e92f9
Call Trace:
[<c01711a9>] generic_file_direct_IO+0x59/0x73
[<c01e92b2>] rw_raw_dev+0xd2/0xf0
[<c01e92f9>] raw_read+0x29/0x30
[<c014c756>] vfs_read+0xb6/0x180
[<c014c3c0>] default_llseek+0x0/0x150
[<c014c63d>] sys_llseek+0x8d/0xf0
[<c014c9ca>] sys_read+0x2a/0x40
[<c010788f>] syscall_call+0x7/0xb

Code: Bad EIP value.



2002-10-10 22:58:07

by Andrew Morton

[permalink] [raw]
Subject: Re: 2.5.41 - kernel NULL pointer

Cliff White wrote:
>
> System is 2-CPU PIII
> Attempting to start the SAP DB. Get this msg:
> SAP cannot open the sys devspace (which is on filesystem)
> DB setup does include one raw partition.
> Further details upon request
> cliffw
>
> Unable to handle kernel NULL pointer dereference at virtual address 00000000
> ...
> [<c01711a9>] generic_file_direct_IO+0x59/0x73

The raw driver was broken by the NFS direct IO merge. It's
unbroken in Linus' current tree. And some additional fixes
are needed on top of that.


--- 2.5.41/fs/direct-io.c~dio-bio-add-fix-1 Thu Oct 10 15:21:51 2002
+++ 2.5.41-akpm/fs/direct-io.c Thu Oct 10 15:52:50 2002
@@ -388,7 +388,7 @@ static void dio_prep_bio(struct dio *dio
/*
* There is no bio. Make one now.
*/
-static int dio_new_bio(struct dio *dio)
+static int dio_new_bio(struct dio *dio, sector_t blkno)
{
sector_t sector;
int ret, nr_pages;
@@ -396,7 +396,7 @@ static int dio_new_bio(struct dio *dio)
ret = dio_bio_reap(dio);
if (ret)
goto out;
- sector = dio->next_block_in_bio << (dio->blkbits - 9);
+ sector = blkno << (dio->blkbits - 9);
nr_pages = min(dio->pages_left, bio_get_nr_vecs(dio->map_bh.b_bdev));
BUG_ON(nr_pages <= 0);
ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, nr_pages);
@@ -408,22 +408,28 @@ out:

static int
dio_bio_add_page(struct dio *dio, struct page *page,
- unsigned int bv_len, unsigned int bv_offset)
+ unsigned int bv_len, unsigned int bv_offset, sector_t blkno)
{
int ret = 0;

if (bv_len == 0)
goto out;

+ /* Take a ref against the page each time it is placed into a BIO */
page_cache_get(page);
if (bio_add_page(dio->bio, page, bv_len, bv_offset)) {
dio_bio_submit(dio);
- ret = dio_new_bio(dio);
+ ret = dio_new_bio(dio, blkno);
if (ret == 0) {
ret = bio_add_page(dio->bio, page, bv_len, bv_offset);
BUG_ON(ret != 0);
+ } else {
+ /* The page didn't make it into a BIO */
+ page_cache_release(page);
}
}
+
+ /* Drop the ref which was taken in get_user_pages() */
page_cache_release(page);
dio->pages_left--;
out:
@@ -460,6 +466,7 @@ int do_direct_IO(struct dio *dio)
int new_page; /* Need to insert this page into the BIO? */
unsigned int bv_offset;
unsigned int bv_len;
+ sector_t curr_blkno;

page = dio_get_page(dio);
if (IS_ERR(page)) {
@@ -470,6 +477,7 @@ int do_direct_IO(struct dio *dio)
new_page = 1;
bv_offset = 0;
bv_len = 0;
+ curr_blkno = 0;
while (block_in_page < blocks_per_page) {
unsigned this_chunk_bytes; /* # of bytes mapped */
unsigned this_chunk_blocks; /* # of blocks */
@@ -494,7 +502,7 @@ int do_direct_IO(struct dio *dio)

dio_prep_bio(dio);
if (dio->bio == NULL) {
- ret = dio_new_bio(dio);
+ ret = dio_new_bio(dio, dio->next_block_in_bio);
if (ret)
goto out;
new_page = 1;
@@ -503,6 +511,7 @@ int do_direct_IO(struct dio *dio)
if (new_page) {
bv_len = 0;
bv_offset = block_in_page << blkbits;
+ curr_blkno = dio->next_block_in_bio;
new_page = 0;
}

@@ -530,7 +539,7 @@ next_block:
if (dio->block_in_file == dio->final_block_in_request)
break;
}
- ret = dio_bio_add_page(dio, page, bv_len, bv_offset);
+ ret = dio_bio_add_page(dio, page, bv_len, bv_offset, curr_blkno);
if (ret)
goto out;
block_in_page = 0;

.