diff -ur a/fs/ext4/ext4.h b/fs/ext4/ext4.h --- a/fs/ext4/ext4.h 2013-03-14 12:04:44.105541822 -0400 +++ b/fs/ext4/ext4.h 2013-03-14 12:09:14.264489405 -0400 @@ -1661,6 +1661,8 @@ extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); +extern int ext4_map_inode_page(struct inode *inode, struct page *page, + sector_t *blocks, int create); extern qsize_t *ext4_get_reserved_space(struct inode *inode); extern int flush_aio_dio_completed_IO(struct inode *inode); extern void ext4_da_update_reserve_space(struct inode *inode, diff -ur a/fs/ext4/inode.c b/fs/ext4/inode.c --- a/fs/ext4/inode.c 2013-03-14 12:04:44.103541330 -0400 +++ b/fs/ext4/inode.c 2013-03-14 12:11:16.526353498 -0400 @@ -6131,3 +6131,62 @@ out: return ret; } + +int ext4_map_inode_page(struct inode *inode, struct page *page, + sector_t *blocks, int create) +{ + unsigned int blocksize, blocks_per_page; + unsigned long iblock; + struct buffer_head dummy; + void *handle; + int i, rc = 0, failed = 0, needed_blocks; + + blocksize = inode->i_sb->s_blocksize; + blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; + iblock = page->index * blocks_per_page; + + for (i = 0; i < blocks_per_page; i++, iblock++) { + blocks[i] = ext4_bmap(inode->i_mapping, iblock); + if (blocks[i] == 0) { + failed++; + } + } + + if (failed == 0 || create == 0) + return 0; + + needed_blocks = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, needed_blocks); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + iblock = page->index * blocks_per_page; + for (i = 0; i < blocks_per_page; i++, iblock++) { + if (blocks[i] != 0) + continue; + + rc = ext4_ind_get_blocks(handle, inode, iblock, 1, &dummy, + EXT4_GET_BLOCKS_CREATE); + if (rc < 0) { + printk(KERN_INFO "ext4_map_inode_page: error reading " + "block %ld\n", iblock); + goto out; + } else { + if (rc > 1) + WARN_ON(1); + rc = 0; + } + /* Unmap any metadata buffers from the block mapping, to avoid + * data corruption due to direct-write from Lustre being + * clobbered by a later flush of the blockdev metadata buffer.*/ + if (buffer_new(&dummy)) + unmap_underlying_metadata(dummy.b_bdev, + dummy.b_blocknr); + blocks[i] = dummy.b_blocknr; + } + +out: + ext4_journal_stop(handle); + return rc; +} +EXPORT_SYMBOL(ext4_map_inode_page);