Oops in block_read_full_page()

Message ID 20001029161322.A1198@arthur.ubicom.tudelft.nl
State New, archived
Headers show
Series
  • Oops in block_read_full_page()
Related show

Commit Message

Erik Mouw Oct. 29, 2000, 3:13 p.m. UTC
Hi,

I just got an Oops in block_read_full_page() (fs/buffer.c) in
test10-pre6 while logging out from X. The system is an Asus P6300
notebook with Mobile PII/266 and 112MB memory running SuSE 6.4.
Here is the output from ksymoops:


ksymoops 0.7c on i686 2.4.0-test10.  Options used
     -V (default)
     -k /proc/ksyms (default)
     -l /proc/modules (default)
     -o /lib/modules/2.4.0-test10/ (default)
     -m /usr/src/linux/System.map (default)

Warning: You did not tell me where to find symbol information.  I will
assume that the log matches the kernel and modules that are running
right now and I'll use the default options above for symbol resolution.
If the current kernel and/or modules do not match the log, you can get
more accurate output by telling me the kernel version and where to find
map, modules, ksyms etc.  ksymoops -h explains the options.

Warning (compare_maps): snd symbol pm_register not found in /lib/modules/2.4.0-test10/misc/snd.o.  Ignoring /lib/modules/2.4.0-test10/misc/snd.o entry
Warning (compare_maps): snd symbol pm_send not found in /lib/modules/2.4.0-test10/misc/snd.o.  Ignoring /lib/modules/2.4.0-test10/misc/snd.o entry
Warning (compare_maps): snd symbol pm_unregister not found in /lib/modules/2.4.0-test10/misc/snd.o.  Ignoring /lib/modules/2.4.0-test10/misc/snd.o entry
Unable to handle kernel NULL pointer dereference at virtual address 00000010
c012fb46
*pde = 00000000
Oops: 0000
CPU:    0
EIP:    0010:[<c012fb46>]
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010282
eax: 00000000   ebx: 00000000   ecx: c421ff24   edx: c111f030
esi: c111f030   edi: c412a5dc   ebp: 00000000   esp: c4321ee4
ds: 0018   es: 0018   ss: 0018
Process tcsh (pid: 439, stackpage=c4321000)
Stack: 00000000 c111f030 c412a5dc 00000000 0000001f 00000000 c0224540 00000246 
       c012275e 00000000 c111f030 c412a5dc 00000000 c4321f1c 01234567 c4320000 
       c111f05c c421ff24 c014a54f c111f030 c0149ec8 c0123005 c4805540 c111f030 
Call Trace: [<c012275e>] [<c014a54f>] [<c0149ec8>] [<c0123005>] [<c01232df>] [<c0123230>] [<c012d646>] 
       [<c010a317>] 
Code: 8b 40 10 89 44 24 24 c7 44 24 18 00 00 00 00 8b 42 18 a8 01 

>>EIP; c012fb46 <block_read_full_page+e/1e8>   <=====
Trace; c012275e <___wait_on_page+ca/d4>
Trace; c014a54f <ext2_readpage+f/14>
Trace; c0149ec8 <ext2_get_block+0/490>
Trace; c0123005 <do_generic_file_read+29d/4c8>
Trace; c01232df <generic_file_read+5b/78>
Trace; c0123230 <file_read_actor+0/54>
Trace; c012d646 <sys_read+96/cc>
Trace; c010a317 <system_call+33/38>
Code;  c012fb46 <block_read_full_page+e/1e8>
00000000 <_EIP>:
Code;  c012fb46 <block_read_full_page+e/1e8>   <=====
   0:   8b 40 10                  mov    0x10(%eax),%eax   <=====
Code;  c012fb49 <block_read_full_page+11/1e8>
   3:   89 44 24 24               mov    %eax,0x24(%esp,1)
Code;  c012fb4d <block_read_full_page+15/1e8>
   7:   c7 44 24 18 00 00 00      movl   $0x0,0x18(%esp,1)
Code;  c012fb54 <block_read_full_page+1c/1e8>
   e:   00 
Code;  c012fb55 <block_read_full_page+1d/1e8>
   f:   8b 42 18                  mov    0x18(%edx),%eax
Code;  c012fb58 <block_read_full_page+20/1e8>
  12:   a8 01                     test   $0x1,%al


4 warnings issued.  Results may not be reliable.


I'm using linux-2.4.0-test10-pre6 with John Kennedy's single line
PCMCIA patch and ALSA 0.5.9d (that's what the ksymoops warnings are
coming from).

Closer examination of block_read_full_page() shows that it crashes in
the first line:

      struct inode *inode = (struct inode*)page->mapping->host;

A little bit further in the function, it tests if the page is not
locked:

        if (!PageLocked(page))
                PAGE_BUG(page);

I'm not an expert in this area, but I can imagine that the inode
extraction in the first line fails if there is something wrong with the
page parameter itself. To catch those cases, I'd like to propose the
following diff:


I'm currently running a kernel with this diff applied, but haven't yet
succeeded in reproducing the Oops. Config file is attached.


Erik

Patch

--- linux-2.4.0-test10-pre6/fs/buffer.c.old	Sun Oct 29 15:28:56 2000
+++ linux-2.4.0-test10-pre6/fs/buffer.c	Sun Oct 29 15:29:35 2000
@@ -1581,7 +1581,7 @@ 
  */
 int block_read_full_page(struct page *page, get_block_t *get_block)
 {
-	struct inode *inode = (struct inode*)page->mapping->host;
+	struct inode *inode;
 	unsigned long iblock, lblock;
 	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
 	unsigned int blocksize, blocks;
@@ -1590,6 +1590,9 @@ 
 
 	if (!PageLocked(page))
 		PAGE_BUG(page);
+
+	inode = (struct inode*)page->mapping->host;
+
 	blocksize = inode->i_sb->s_blocksize;
 	if (!page->buffers)
 		create_empty_buffers(page, inode, blocksize);