--- sles/fs/mpage.c.~1~ 2004-07-09 23:48:33.233205496 +0200 +++ sles/fs/mpage.c 2004-07-10 06:32:24.784449776 +0200 @@ -404,6 +404,7 @@ mpage_writepage(struct bio *bio, struct struct block_device *boundary_bdev = NULL; int length; struct buffer_head map_bh; + loff_t i_size = i_size_read(inode); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -460,7 +461,7 @@ mpage_writepage(struct bio *bio, struct */ BUG_ON(!PageUptodate(page)); block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits); - last_block = (i_size_read(inode) - 1) >> blkbits; + last_block = (i_size - 1) >> blkbits; map_bh.b_page = page; for (page_block = 0; page_block < blocks_per_page; ) { @@ -490,9 +491,11 @@ mpage_writepage(struct bio *bio, struct first_unmapped = page_block; - end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; +page_is_mapped: + + end_index = i_size >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { - unsigned offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1); + unsigned offset = i_size & (PAGE_CACHE_SIZE - 1); char *kaddr; if (page->index > end_index || !offset) @@ -503,8 +506,6 @@ mpage_writepage(struct bio *bio, struct kunmap_atomic(kaddr, KM_USER0); } -page_is_mapped: - /* * This page will go to BIO. Do we need to send this BIO off first? */ @@ -519,6 +520,12 @@ alloc_new: goto confused; } + length = first_unmapped << blkbits; + if (bio_add_page(bio, page, length, 0) < length) { + bio = mpage_bio_submit(WRITE, bio); + goto alloc_new; + } + /* * OK, we have our BIO, so we can now mark the buffers clean. Make * sure to only clean buffers which we know we'll be writing. @@ -539,12 +546,6 @@ alloc_new: try_to_free_buffers(page); } - length = first_unmapped << blkbits; - if (bio_add_page(bio, page, length, 0) < length) { - bio = mpage_bio_submit(WRITE, bio); - goto alloc_new; - } - BUG_ON(PageWriteback(page)); set_page_writeback(page); unlock_page(page); --- sles/fs/buffer.c.~1~ 2004-07-05 03:08:09.000000000 +0200 +++ sles/fs/buffer.c 2004-07-09 05:16:47.544011656 +0200 @@ -1586,10 +1586,9 @@ __bread(struct block_device *bdev, secto EXPORT_SYMBOL(__bread); /* - * invalidate_bh_lrus() is called rarely - at unmount. Because it is only for - * unmount it only needs to ensure that all buffers from the target device are - * invalidated on return and it doesn't need to worry about new buffers from - * that device being added - the unmount code has to prevent that. + * invalidate_bh_lrus() is called rarely - but not only at unmount. + * This doesn't race because it runs in each cpu either in irq + * or with preempt disabled. */ static void invalidate_bh_lru(void *arg) {