add patch fix-an-endianness-bug-in-ext4_encrypted_follow_link
[ext4-patch-queue.git] / implement-allocation-of-pre-zeroed-blocks
blobd9a41d65361f7766627b34dc1542331524998186
1 ext4: implement allocation of pre-zeroed blocks
3 From: Jan Kara <jack@suse.com>
5 DAX page fault path needs to get blocks that are pre-zeroed to avoid
6 races when two concurrent page faults happen in the same block of a
7 file. Implement support for this in ext4_map_blocks().
9 Signed-off-by: Jan Kara <jack@suse.com>
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
11 ---
12  fs/ext4/ext4.h              |  4 ++++
13  fs/ext4/extents.c           |  8 ++++++++
14  fs/ext4/inode.c             | 20 +++++++++++++++++---
15  include/trace/events/ext4.h |  3 ++-
16  4 files changed, 31 insertions(+), 4 deletions(-)
18 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
19 index 785737a342e6..0a11a34d54c9 100644
20 --- a/fs/ext4/ext4.h
21 +++ b/fs/ext4/ext4.h
22 @@ -553,6 +553,10 @@ enum {
23  #define EXT4_GET_BLOCKS_KEEP_SIZE              0x0080
24         /* Convert written extents to unwritten */
25  #define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN      0x0100
26 +       /* Write zeros to newly created written extents */
27 +#define EXT4_GET_BLOCKS_ZERO                   0x0200
28 +#define EXT4_GET_BLOCKS_CREATE_ZERO            (EXT4_GET_BLOCKS_CREATE |\
29 +                                       EXT4_GET_BLOCKS_ZERO)
31  /*
32   * The bit position of these flags must not overlap with any of the
33 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
34 index 273bf40cca23..8e0d853a8044 100644
35 --- a/fs/ext4/extents.c
36 +++ b/fs/ext4/extents.c
37 @@ -4040,6 +4040,14 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
38         }
39         /* IO end_io complete, convert the filled extent to written */
40         if (flags & EXT4_GET_BLOCKS_CONVERT) {
41 +               if (flags & EXT4_GET_BLOCKS_ZERO) {
42 +                       if (allocated > map->m_len)
43 +                               allocated = map->m_len;
44 +                       err = ext4_issue_zeroout(inode, map->m_lblk, newblock,
45 +                                                allocated);
46 +                       if (err < 0)
47 +                               goto out2;
48 +               }
49                 ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
50                                                            ppath);
51                 if (ret >= 0) {
52 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
53 index 5e5795bde6b4..73c6214084d4 100644
54 --- a/fs/ext4/inode.c
55 +++ b/fs/ext4/inode.c
56 @@ -643,7 +643,7 @@ found:
57                 if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
58                     ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
59                         if (ext4_es_is_written(&es))
60 -                               goto has_zeroout;
61 +                               goto out_sem;
62                 }
63                 status = map->m_flags & EXT4_MAP_UNWRITTEN ?
64                                 EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
65 @@ -654,11 +654,24 @@ found:
66                         status |= EXTENT_STATUS_DELAYED;
67                 ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
68                                             map->m_pblk, status);
69 -               if (ret < 0)
70 +               if (ret < 0) {
71                         retval = ret;
72 +                       goto out_sem;
73 +               }
75 +               if (flags & EXT4_GET_BLOCKS_ZERO &&
76 +                   map->m_flags & EXT4_MAP_MAPPED &&
77 +                   map->m_flags & EXT4_MAP_NEW) {
78 +                       ret = ext4_issue_zeroout(inode, map->m_lblk,
79 +                                                map->m_pblk, map->m_len);
80 +                       if (ret) {
81 +                               retval = ret;
82 +                               goto out_sem;
83 +                       }
84 +               }
85         }
87 -has_zeroout:
88 +out_sem:
89         up_write((&EXT4_I(inode)->i_data_sem));
90         if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
91                 ret = check_block_validity(inode, map);
92 @@ -3041,6 +3054,7 @@ int ext4_get_block_dax(struct inode *inode, sector_t iblock,
93                    struct buffer_head *bh_result, int create)
94  {
95         int flags = EXT4_GET_BLOCKS_PRE_IO | EXT4_GET_BLOCKS_UNWRIT_EXT;
97         if (create)
98                 flags |= EXT4_GET_BLOCKS_CREATE;
99         ext4_debug("ext4_get_block_dax: inode %lu, create flag %d\n",
100 diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
101 index 5f2ace56efc5..4e4b2fa78609 100644
102 --- a/include/trace/events/ext4.h
103 +++ b/include/trace/events/ext4.h
104 @@ -42,7 +42,8 @@ struct extent_status;
105         { EXT4_GET_BLOCKS_CONVERT,              "CONVERT" },            \
106         { EXT4_GET_BLOCKS_METADATA_NOFAIL,      "METADATA_NOFAIL" },    \
107         { EXT4_GET_BLOCKS_NO_NORMALIZE,         "NO_NORMALIZE" },       \
108 -       { EXT4_GET_BLOCKS_KEEP_SIZE,            "KEEP_SIZE" })
109 +       { EXT4_GET_BLOCKS_KEEP_SIZE,            "KEEP_SIZE" },          \
110 +       { EXT4_GET_BLOCKS_ZERO,                 "ZERO" })
112  #define show_mflags(flags) __print_flags(flags, "",    \
113         { EXT4_MAP_NEW,         "N" },                  \
114 -- 
115 2.1.4
118 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
119 the body of a message to majordomo@vger.kernel.org
120 More majordomo info at  http://vger.kernel.org/majordomo-info.html