Whamcloud - gitweb
LU-1812 ldiskfs: Add kernel patch series for SLES11SP2
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / sles11sp2 / ext4-map_inode_page-3.0.patch
1 ---
2  fs/ext4/ext4.h  |    3 ++
3  fs/ext4/inode.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4  2 files changed, 71 insertions(+)
5
6 --- a/fs/ext4/ext4.h
7 +++ b/fs/ext4/ext4.h
8 @@ -1838,6 +1838,9 @@ extern int ext4_page_mkwrite(struct vm_a
9  extern qsize_t *ext4_get_reserved_space(struct inode *inode);
10  extern void ext4_da_update_reserve_space(struct inode *inode,
11                                         int used, int quota_claim);
12 +extern int ext4_map_inode_page(struct inode *inode, struct page *page,
13 +                              unsigned long *blocks, int *created,
14 +                              int create);
15  /* ioctl.c */
16  extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
17  extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
18 --- a/fs/ext4/inode.c
19 +++ b/fs/ext4/inode.c
20 @@ -5968,3 +5968,71 @@ out_unlock:
21         up_read(&inode->i_alloc_sem);
22         return ret;
23  }
24 +
25 +int ext4_map_inode_page(struct inode *inode, struct page *page,
26 +                       unsigned long *blocks, int *created, int create)
27 +{
28 +       unsigned int blocksize, blocks_per_page;
29 +       unsigned long iblock;
30 +       struct ext4_map_blocks map;
31 +       void *handle;
32 +       int i, rc = 0, failed = 0, needed_blocks;
33 +
34 +       blocksize = inode->i_sb->s_blocksize;
35 +       blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
36 +       iblock = page->index * blocks_per_page;
37 +
38 +       for (i = 0; i < blocks_per_page; i++, iblock++) {
39 +               blocks[i] = ext4_bmap(inode->i_mapping, iblock);
40 +               if (blocks[i] == 0) {
41 +                       failed++;
42 +                       if (created)
43 +                               created[i] = -1;
44 +               } else if (created) {
45 +                       created[i] = 0;
46 +               }
47 +       }
48 +
49 +       if (failed == 0 || create == 0)
50 +               return 0;
51 +
52 +       needed_blocks = ext4_writepage_trans_blocks(inode);
53 +       handle = ext4_journal_start(inode, needed_blocks);
54 +       if (IS_ERR(handle))
55 +               return PTR_ERR(handle);
56 +
57 +       iblock = page->index * blocks_per_page;
58 +       for (i = 0; i < blocks_per_page; i++, iblock++) {
59 +               if (blocks[i] != 0)
60 +                       continue;
61 +
62 +               map.m_lblk = iblock;
63 +               map.m_len = 1;
64 +               map.m_flags = 0;
65 +               rc = ext4_ind_map_blocks(handle, inode, &map,
66 +                                        EXT4_GET_BLOCKS_CREATE);
67 +               if (rc < 0) {
68 +                       printk(KERN_INFO "ext4_map_inode_page: error reading "
69 +                                       "block %ld\n", iblock);
70 +                       goto out;
71 +               } else {
72 +                       if (rc > 1)
73 +                               WARN_ON(1);
74 +                       rc = 0;
75 +               }
76 +               /* Unmap any metadata buffers from the block mapping, to avoid
77 +                * data corruption due to direct-write from Lustre being
78 +                * clobbered by a later flush of the blockdev metadata buffer.*/
79 +               if (map.m_flags & EXT4_MAP_NEW)
80 +                       unmap_underlying_metadata(inode->i_sb->s_bdev,
81 +                                       map.m_pblk);
82 +               blocks[i] = map.m_pblk;
83 +               if (created)
84 +                       created[i] = 1;
85 +       }
86 +
87 +out:
88 +       ext4_journal_stop(handle);
89 +       return rc;
90 +}
91 +EXPORT_SYMBOL(ext4_map_inode_page);