Whamcloud - gitweb
LU-2748 fsfilt: ext4_map_inode_page in osd and ldisk out of sync
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / rhel6.3 / ext4-map_inode_page-2.6.18.patch
1 diff -ur a/fs/ext4/ext4.h b/fs/ext4/ext4.h
2 --- a/fs/ext4/ext4.h    2013-03-14 12:04:44.105541822 -0400
3 +++ b/fs/ext4/ext4.h    2013-03-14 12:09:14.264489405 -0400
4 @@ -1661,6 +1661,8 @@
5  extern int ext4_block_truncate_page(handle_t *handle,
6                 struct address_space *mapping, loff_t from);
7  extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
8 +extern int ext4_map_inode_page(struct inode *inode, struct page *page,
9 +                               unsigned long *blocks, int create);
10  extern qsize_t *ext4_get_reserved_space(struct inode *inode);
11  extern int flush_aio_dio_completed_IO(struct inode *inode);
12  extern void ext4_da_update_reserve_space(struct inode *inode,
13 diff -ur a/fs/ext4/inode.c b/fs/ext4/inode.c
14 --- a/fs/ext4/inode.c   2013-03-14 12:04:44.103541330 -0400
15 +++ b/fs/ext4/inode.c   2013-03-14 12:11:16.526353498 -0400
16 @@ -6131,3 +6131,62 @@
17  out:
18          return ret;
19  }
20 +
21 +int ext4_map_inode_page(struct inode *inode, struct page *page,
22 +                       unsigned long *blocks, int create)
23 +{
24 +       unsigned int blocksize, blocks_per_page;
25 +       unsigned long iblock;
26 +       struct buffer_head dummy;
27 +       void *handle;
28 +       int i, rc = 0, failed = 0, needed_blocks;
29 +
30 +       blocksize = inode->i_sb->s_blocksize;
31 +       blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
32 +       iblock = page->index * blocks_per_page;
33 +
34 +       for (i = 0; i < blocks_per_page; i++, iblock++) {
35 +               blocks[i] = ext4_bmap(inode->i_mapping, iblock);
36 +               if (blocks[i] == 0) {
37 +                       failed++;
38 +               }
39 +       }
40 +
41 +       if (failed == 0 || create == 0)
42 +               return 0;
43 +
44 +       needed_blocks = ext4_writepage_trans_blocks(inode);
45 +       handle = ext4_journal_start(inode, needed_blocks);
46 +       if (IS_ERR(handle))
47 +               return PTR_ERR(handle);
48 +
49 +       iblock = page->index * blocks_per_page;
50 +       for (i = 0; i < blocks_per_page; i++, iblock++) {
51 +               if (blocks[i] != 0)
52 +                       continue;
53 +
54 +               rc = ext4_ind_get_blocks(handle, inode, iblock, 1, &dummy,
55 +                                        EXT4_GET_BLOCKS_CREATE);
56 +               if (rc < 0) {
57 +                       printk(KERN_INFO "ext4_map_inode_page: error reading "
58 +                                       "block %ld\n", iblock);
59 +                       goto out;
60 +               } else {
61 +                       if (rc > 1)
62 +                               WARN_ON(1);
63 +                       rc = 0;
64 +               }
65 +               /* Unmap any metadata buffers from the block mapping, to avoid
66 +                * data corruption due to direct-write from Lustre being
67 +                * clobbered by a later flush of the blockdev metadata buffer.*/
68 +               if (buffer_new(&dummy))
69 +                       unmap_underlying_metadata(dummy.b_bdev,
70 +                                       dummy.b_blocknr);
71 +               blocks[i] = dummy.b_blocknr;
72 +       }
73 +
74 +out:
75 +       ext4_journal_stop(handle);
76 +       return rc;
77 +}
78 +EXPORT_SYMBOL(ext4_map_inode_page);