diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 25 |
1 files changed, 22 insertions, 3 deletions
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 | ||
661 | has_zeroout: | 679 | out_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", |