Hi Andrew, Due to lack of interesting suggestions to solve mpage_writepages() -> ext3_writeback_writepage() problem, I fixed it in the dumbest possible way.
Please don't kill me :) Let me know, what you think. Thanks, Badari
diff -Naurp linux-2.6.10/include/linux/fs.h linux-2.6.10.new/include/linux/fs.h --- linux-2.6.10/include/linux/fs.h 2004-12-24 13:34:27.000000000 -0800 +++ linux-2.6.10.new/include/linux/fs.h 2005-02-11 15:39:12.000000000 -0800 @@ -27,6 +27,7 @@ struct poll_table_struct; struct kstatfs; struct vm_area_struct; struct vfsmount; +struct writeback_control; /* * It's silly to have NR_OPEN bigger than NR_FILE, but you can change @@ -244,6 +245,8 @@ typedef int (get_blocks_t)(struct inode struct buffer_head *bh_result, int create); typedef void (dio_iodone_t)(struct inode *inode, loff_t offset, ssize_t bytes, void *private); +typedef int (writepage_t)(struct page *page, struct writeback_control *wbc); /* * Attribute flags. These should be or-ed together to figure out what diff -Naurp linux-2.6.10/include/linux/mpage.h linux-2.6.10.new/include/linux/mpage.h --- linux-2.6.10/include/linux/mpage.h 2004-12-24 13:34:32.000000000 -0800 +++ linux-2.6.10.new/include/linux/mpage.h 2005-02-11 15:40:26.000000000 -0800 @@ -17,6 +17,9 @@ int mpage_readpages(struct address_space int mpage_readpage(struct page *page, get_block_t get_block); int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block); +int __mpage_writepages(struct address_space *mapping, + struct writeback_control *wbc, get_block_t get_block, + writepage_t writepage); static inline int generic_writepages(struct address_space *mapping, struct writeback_control *wbc) --- linux-2.6.10/fs/mpage.c 2004-12-24 13:34:26.000000000 -0800 +++ linux-2.6.10.new/fs/mpage.c 2005-02-11 16:14:39.338838584 -0800 @@ -387,7 +387,8 @@ EXPORT_SYMBOL(mpage_readpage); */ static struct bio * mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, - sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc) + sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc, + writepage_t writepage_helper) { struct address_space *mapping = page->mapping; struct inode *inode = page->mapping->host; @@ -580,7 +581,7 @@ alloc_new: confused: if (bio) bio = mpage_bio_submit(WRITE, bio); - *ret = page->mapping->a_ops->writepage(page, wbc); + *ret = writepage_helper(page, wbc); /* * The caller has a ref on the inode, so *mapping is stable */ @@ -619,6 +620,15 @@ int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { + return __mpage_writepages(mapping, wbc, get_block, + mapping->a_ops->writepage); +} + +int +__mpage_writepages(struct address_space *mapping, + struct writeback_control *wbc, get_block_t get_block, + writepage_t writepage_helper) +{ struct backing_dev_info *bdi = mapping->backing_dev_info; struct bio *bio = NULL; sector_t last_block_in_bio = 0; @@ -707,7 +717,8 @@ retry: } } else { bio = mpage_writepage(bio, page, get_block, - &last_block_in_bio, &ret, wbc); + &last_block_in_bio, &ret, wbc, + writepage_helper); } if (ret || (--(wbc->nr_to_write) <= 0)) done = 1; @@ -735,3 +746,4 @@ retry: return ret; } EXPORT_SYMBOL(mpage_writepages); +EXPORT_SYMBOL(__mpage_writepages); --- linux-2.6.10/fs/ext3/inode.c 2004-12-24 13:35:01.000000000 -0800 +++ linux-2.6.10.new/fs/ext3/inode.c 2005-02-11 16:16:02.566186104 -0800 @@ -856,6 +856,12 @@ get_block: return ret; } +static int ext3_writepages_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + return ext3_direct_io_get_blocks(inode, iblock, 1, bh, create); +} + /* * `handle' can be NULL if create is zero */ @@ -1321,6 +1327,44 @@ out_fail: return ret; } +static int ext3_writeback_writepage_helper(struct page *page, + struct writeback_control *wbc) +{ + return block_write_full_page(page, ext3_get_block, wbc); +} + +static int +ext3_writeback_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct inode *inode = mapping->host; + handle_t *handle = NULL; + int err, ret = 0; + + if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) + return ret; + + handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); + return ret; + } + + ret = __mpage_writepages(mapping, wbc, ext3_writepages_get_block, + ext3_writeback_writepage_helper); + + /* + * Need to reaquire the handle since ext3_writepages_get_block() + * can restart the handle + */ + handle = journal_current_handle(); + + err = ext3_journal_stop(handle); + if (!ret) + ret = err; + return ret; +} + static int ext3_writeback_writepage(struct page *page, struct writeback_control *wbc) { @@ -1552,6 +1596,7 @@ static struct address_space_operations e .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_writeback_writepage, + .writepages = ext3_writeback_writepages, .sync_page = block_sync_page, .prepare_write = ext3_prepare_write, .commit_write = ext3_writeback_commit_write,