=========================================================================== 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); }