[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Kernel oops on new mailserver



On Tue, 2002-03-26 at 05:24, Paul Schutte wrote:
> Hi,
> 
> It happened again.
> 
> Dell PE2550
> 1G RAM
> 2 x 1.133GHz CPUs
> 4x18Gb Seagate cheeta's in RAID 10 on Perc hardware RAID
> 
> kernel 2.4.18 (checked out on 21 March 2002 ) after the following take:
> 

Don't worry, I have not forgotten you! Nathan's change is mostly all
formatting, no real structural changes in there.


Can you try this code?

Thanks,

Steve



Steve Lord                                      voice: +1-651-683-3511
Principal Engineer, Filesystem Software         email: lord@sgi.com

===========================================================================
Index: linux/fs/xfs/pagebuf/page_buf_io.c
===========================================================================

--- /usr/tmp/TmpDir.17165-0/linux/fs/xfs/pagebuf/page_buf_io.c_1.18	Tue Mar 26 08:31:11 2002
+++ linux/fs/xfs/pagebuf/page_buf_io.c	Mon Mar 25 12:50:15 2002
@@ -638,12 +638,12 @@
 		
 		error = bmap(inode, ((loff_t)page->index << PAGE_CACHE_SHIFT),
 				PAGE_CACHE_SIZE, &map, 1, &nmaps, PBF_READ);
+
+		hook_buffers_to_page(target, inode, page, &map, nmaps);
+		bh = head = page->buffers;
 		if (error)
 			BUG();
-		if (map.pbm_bn >= 0) {
-			hook_buffers_to_page(target, inode, page, &map, nmaps);
-			bh = head = page->buffers;
-		} else if (map.pbm_flags & (PBMF_HOLE|PBMF_DELAY)) {
+		if (map.pbm_flags & (PBMF_HOLE|PBMF_DELAY)) {
 			memset(kmap(page), 0, PAGE_CACHE_SIZE);
 			flush_dcache_page(page);
 			kunmap(page);
@@ -754,11 +754,10 @@
 {
 	struct buffer_head 	*bh;
 
-	if (page->buffers)
-		BUG();
-	create_empty_buffers(page, target->pbr_device, PAGE_CACHE_SIZE);
+	if (!page->buffers)
+		create_empty_buffers(page, target->pbr_device, PAGE_CACHE_SIZE);
 	bh = page->buffers;
-	bh->b_state = (1 << BH_Delay) | (1 << BH_Mapped);
+	bh->b_state = (1 << BH_Delay) | (1 << BH_Mapped) | (1 << BH_Uptodate);
 	__mark_buffer_dirty(bh);
 	buffer_insert_inode_data_queue(bh, inode);
 	balance_dirty();
@@ -785,19 +784,22 @@
 	 * delta = offset of _this_ page in extent.
 	 * pbm_offset = offset in file corresponding to pbm_bn.
 	 */
-	delta = page->index;	    /* do computations in 64 bit ...   */
-	delta <<= PAGE_CACHE_SHIFT; /* delta now offset from 0 of page */
-	delta -= mp->pbm_offset;    /* delta now offset in extent of page */
-
-	bn = mp->pbm_bn >>
-		(PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
-	bn += (delta >> PAGE_CACHE_SHIFT);
-	lock_buffer(bh);
-	bh->b_blocknr = bn;
-	bh->b_dev = target->pbr_device;
-	set_bit(BH_Mapped, &bh->b_state);
-	clear_bit(BH_Delay, &bh->b_state);
-	unlock_buffer(bh);
+
+	if (mp->pbm_bn >= 0) {
+		delta = page->index;	    /* do computations in 64 bit  */
+		delta <<= PAGE_CACHE_SHIFT; /* delta is offset from 0 of page */
+		delta -= mp->pbm_offset;    /* delta is offset in extent */
+		bn = mp->pbm_bn >>
+			(PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+		bn += (delta >> PAGE_CACHE_SHIFT);
+		bh = page->buffers;
+		lock_buffer(bh);
+		bh->b_blocknr = bn; 
+		bh->b_dev = target->pbr_device;
+		set_bit(BH_Mapped, &bh->b_state);
+		clear_bit(BH_Delay, &bh->b_state);
+		unlock_buffer(bh);
+	}
 }
 
 STATIC void
@@ -809,13 +811,9 @@
 	int need_balance_dirty = 0;
 
 #ifdef PAGEBUF_DEBUG
-	/* negative blocknr is always bad; if it's zero, and the
-	 * inode & bh are on different devices, it could be an
-	 * xfs realtime file, which would be OK.  Either that
-	 * or something is seriously wrong!
+	/* negative blocknr is always bad; 
 	 */
-	if ((bh->b_blocknr < 0) || 
-	    ((bh->b_blocknr == 0) && (inode->i_dev == bh->b_dev))) {
+	if (bh->b_blocknr < 0) {
 		printk("Warning: buffer 0x%p with weird blockno (%ld)\n",
 			bh, bh->b_blocknr);
 	}
@@ -860,8 +858,10 @@
 	 * go get some space.
 	 */
 	bh = page->buffers;
+/***
 	if ((!bh || buffer_delay(bh)) && (!dp || (flags & PBF_FILE_ALLOCATE)))
-	{
+***/
+	if (!bh || !buffer_mapped(bh)) {
 		if (!mp) {
 			mp = map;
 			err = bmap(inode, ((loff_t)page->index << PAGE_CACHE_SHIFT),
@@ -870,10 +870,8 @@
 				goto out;
 			}
 		}
-		if (mp->pbm_bn >= 0) {
-			hook_buffers_to_page(target, inode, page, mp, nmaps);
-			bh = page->buffers;
-		}
+		hook_buffers_to_page(target, inode, page, mp, nmaps);
+		bh = page->buffers;
 	}
 
 	/* Is the write over the entire page?  */
@@ -961,9 +959,9 @@
 	 * parts of page not covered by from/to. Page is now fully valid.
 	 */
 	SetPageUptodate(page);
-	if ((bh = page->buffers) && !buffer_delay(bh)) {
+	if ((bh = page->buffers) && buffer_mapped(bh)) {
 		set_buffer_dirty_uptodate(inode, page->buffers, partial);
-	} else if (!DelallocPage(page)) {
+	} else {
 		hook_buffers_to_page_delay(target, inode, page);
 	}
 }
@@ -1363,7 +1361,7 @@
 	/* Three possible conditions - page with delayed buffers,
 	 * page with real buffers, or page with no buffers (mmap)
 	 */
-	if (!bh || DelallocPage(page)) {
+	if (!bh || DelallocPage(page) || !buffer_mapped(bh)) {
 		hook_buffers_to_page(target, inode, page, mp, nmaps);
 	}
 
@@ -1424,7 +1422,8 @@
 	loff_t rounded_offset;
 
 	/* Fast path for mapped page */
-	if (page->buffers && !buffer_delay(page->buffers)) {
+	if (page->buffers && !buffer_delay(page->buffers) &&
+	    buffer_mapped(page->buffers)) {
 		if (async_write) {
 			submit_page_io(page);
 		}