aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/extents.c8
-rw-r--r--fs/ext4/inode.c25
-rw-r--r--include/trace/events/ext4.h3
4 files changed, 36 insertions, 4 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ffc6ab000c78..ae900b530d37 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -557,6 +557,10 @@ enum {
557#define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080 557#define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080
558 /* Convert written extents to unwritten */ 558 /* Convert written extents to unwritten */
559#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0100 559#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0100
560 /* Write zeros to newly created written extents */
561#define EXT4_GET_BLOCKS_ZERO 0x0200
562#define EXT4_GET_BLOCKS_CREATE_ZERO (EXT4_GET_BLOCKS_CREATE |\
563 EXT4_GET_BLOCKS_ZERO)
560 564
561/* 565/*
562 * The bit position of these flags must not overlap with any of the 566 * The bit position of these flags must not overlap with any of the
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 867e98b6bc6c..b52fea3b7219 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4044,6 +4044,14 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
4044 } 4044 }
4045 /* IO end_io complete, convert the filled extent to written */ 4045 /* IO end_io complete, convert the filled extent to written */
4046 if (flags & EXT4_GET_BLOCKS_CONVERT) { 4046 if (flags & EXT4_GET_BLOCKS_CONVERT) {
4047 if (flags & EXT4_GET_BLOCKS_ZERO) {
4048 if (allocated > map->m_len)
4049 allocated = map->m_len;
4050 err = ext4_issue_zeroout(inode, map->m_lblk, newblock,
4051 allocated);
4052 if (err < 0)
4053 goto out2;
4054 }
4047 ret = ext4_convert_unwritten_extents_endio(handle, inode, map, 4055 ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
4048 ppath); 4056 ppath);
4049 if (ret >= 0) { 4057 if (ret >= 0) {
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0c9a5ee3e106..4241d0cff062 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -637,13 +637,29 @@ found:
637 } 637 }
638 638
639 /* 639 /*
640 * We have to zeroout blocks before inserting them into extent
641 * status tree. Otherwise someone could look them up there and
642 * use them before they are really zeroed.
643 */
644 if (flags & EXT4_GET_BLOCKS_ZERO &&
645 map->m_flags & EXT4_MAP_MAPPED &&
646 map->m_flags & EXT4_MAP_NEW) {
647 ret = ext4_issue_zeroout(inode, map->m_lblk,
648 map->m_pblk, map->m_len);
649 if (ret) {
650 retval = ret;
651 goto out_sem;
652 }
653 }
654
655 /*
640 * If the extent has been zeroed out, we don't need to update 656 * If the extent has been zeroed out, we don't need to update
641 * extent status tree. 657 * extent status tree.
642 */ 658 */
643 if ((flags & EXT4_GET_BLOCKS_PRE_IO) && 659 if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
644 ext4_es_lookup_extent(inode, map->m_lblk, &es)) { 660 ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
645 if (ext4_es_is_written(&es)) 661 if (ext4_es_is_written(&es))
646 goto has_zeroout; 662 goto out_sem;
647 } 663 }
648 status = map->m_flags & EXT4_MAP_UNWRITTEN ? 664 status = map->m_flags & EXT4_MAP_UNWRITTEN ?
649 EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; 665 EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
@@ -654,11 +670,13 @@ found:
654 status |= EXTENT_STATUS_DELAYED; 670 status |= EXTENT_STATUS_DELAYED;
655 ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, 671 ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
656 map->m_pblk, status); 672 map->m_pblk, status);
657 if (ret < 0) 673 if (ret < 0) {
658 retval = ret; 674 retval = ret;
675 goto out_sem;
676 }
659 } 677 }
660 678
661has_zeroout: 679out_sem:
662 up_write((&EXT4_I(inode)->i_data_sem)); 680 up_write((&EXT4_I(inode)->i_data_sem));
663 if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { 681 if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
664 ret = check_block_validity(inode, map); 682 ret = check_block_validity(inode, map);
@@ -3083,6 +3101,7 @@ int ext4_get_block_dax(struct inode *inode, sector_t iblock,
3083 struct buffer_head *bh_result, int create) 3101 struct buffer_head *bh_result, int create)
3084{ 3102{
3085 int flags = EXT4_GET_BLOCKS_PRE_IO | EXT4_GET_BLOCKS_UNWRIT_EXT; 3103 int flags = EXT4_GET_BLOCKS_PRE_IO | EXT4_GET_BLOCKS_UNWRIT_EXT;
3104
3086 if (create) 3105 if (create)
3087 flags |= EXT4_GET_BLOCKS_CREATE; 3106 flags |= EXT4_GET_BLOCKS_CREATE;
3088 ext4_debug("ext4_get_block_dax: inode %lu, create flag %d\n", 3107 ext4_debug("ext4_get_block_dax: inode %lu, create flag %d\n",
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 5f2ace56efc5..4e4b2fa78609 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -42,7 +42,8 @@ struct extent_status;
42 { EXT4_GET_BLOCKS_CONVERT, "CONVERT" }, \ 42 { EXT4_GET_BLOCKS_CONVERT, "CONVERT" }, \
43 { EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \ 43 { EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \
44 { EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \ 44 { EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \
45 { EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" }) 45 { EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" }, \
46 { EXT4_GET_BLOCKS_ZERO, "ZERO" })
46 47
47#define show_mflags(flags) __print_flags(flags, "", \ 48#define show_mflags(flags) __print_flags(flags, "", \
48 { EXT4_MAP_NEW, "N" }, \ 49 { EXT4_MAP_NEW, "N" }, \