|
@@ -507,12 +507,33 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
|
|
|
int ext4_map_blocks(handle_t *handle, struct inode *inode,
|
|
|
struct ext4_map_blocks *map, int flags)
|
|
|
{
|
|
|
+ struct extent_status es;
|
|
|
int retval;
|
|
|
|
|
|
map->m_flags = 0;
|
|
|
ext_debug("ext4_map_blocks(): inode %lu, flag %d, max_blocks %u,"
|
|
|
"logical block %lu\n", inode->i_ino, flags, map->m_len,
|
|
|
(unsigned long) map->m_lblk);
|
|
|
+
|
|
|
+ /* Lookup extent status tree firstly */
|
|
|
+ if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
|
|
|
+ if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) {
|
|
|
+ map->m_pblk = ext4_es_pblock(&es) +
|
|
|
+ map->m_lblk - es.es_lblk;
|
|
|
+ map->m_flags |= ext4_es_is_written(&es) ?
|
|
|
+ EXT4_MAP_MAPPED : EXT4_MAP_UNWRITTEN;
|
|
|
+ retval = es.es_len - (map->m_lblk - es.es_lblk);
|
|
|
+ if (retval > map->m_len)
|
|
|
+ retval = map->m_len;
|
|
|
+ map->m_len = retval;
|
|
|
+ } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {
|
|
|
+ retval = 0;
|
|
|
+ } else {
|
|
|
+ BUG_ON(1);
|
|
|
+ }
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Try to see if we can get the block without requesting a new
|
|
|
* file system block.
|
|
@@ -544,6 +565,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
|
|
|
if (!(flags & EXT4_GET_BLOCKS_NO_LOCK))
|
|
|
up_read((&EXT4_I(inode)->i_data_sem));
|
|
|
|
|
|
+found:
|
|
|
if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
|
|
|
int ret = check_block_validity(inode, map);
|
|
|
if (ret != 0)
|
|
@@ -1743,6 +1765,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
|
|
|
struct ext4_map_blocks *map,
|
|
|
struct buffer_head *bh)
|
|
|
{
|
|
|
+ struct extent_status es;
|
|
|
int retval;
|
|
|
sector_t invalid_block = ~((sector_t) 0xffff);
|
|
|
|
|
@@ -1753,6 +1776,42 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
|
|
|
ext_debug("ext4_da_map_blocks(): inode %lu, max_blocks %u,"
|
|
|
"logical block %lu\n", inode->i_ino, map->m_len,
|
|
|
(unsigned long) map->m_lblk);
|
|
|
+
|
|
|
+ /* Lookup extent status tree firstly */
|
|
|
+ if (ext4_es_lookup_extent(inode, iblock, &es)) {
|
|
|
+
|
|
|
+ if (ext4_es_is_hole(&es)) {
|
|
|
+ retval = 0;
|
|
|
+ down_read((&EXT4_I(inode)->i_data_sem));
|
|
|
+ goto add_delayed;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Delayed extent could be allocated by fallocate.
|
|
|
+ * So we need to check it.
|
|
|
+ */
|
|
|
+ if (ext4_es_is_delayed(&es) && !ext4_es_is_unwritten(&es)) {
|
|
|
+ map_bh(bh, inode->i_sb, invalid_block);
|
|
|
+ set_buffer_new(bh);
|
|
|
+ set_buffer_delay(bh);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ map->m_pblk = ext4_es_pblock(&es) + iblock - es.es_lblk;
|
|
|
+ retval = es.es_len - (iblock - es.es_lblk);
|
|
|
+ if (retval > map->m_len)
|
|
|
+ retval = map->m_len;
|
|
|
+ map->m_len = retval;
|
|
|
+ if (ext4_es_is_written(&es))
|
|
|
+ map->m_flags |= EXT4_MAP_MAPPED;
|
|
|
+ else if (ext4_es_is_unwritten(&es))
|
|
|
+ map->m_flags |= EXT4_MAP_UNWRITTEN;
|
|
|
+ else
|
|
|
+ BUG_ON(1);
|
|
|
+
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Try to see if we can get the block without requesting a new
|
|
|
* file system block.
|
|
@@ -1771,10 +1830,13 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
|
|
|
map->m_flags |= EXT4_MAP_FROM_CLUSTER;
|
|
|
retval = 0;
|
|
|
} else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
|
|
- retval = ext4_ext_map_blocks(NULL, inode, map, 0);
|
|
|
+ retval = ext4_ext_map_blocks(NULL, inode, map,
|
|
|
+ EXT4_GET_BLOCKS_NO_PUT_HOLE);
|
|
|
else
|
|
|
- retval = ext4_ind_map_blocks(NULL, inode, map, 0);
|
|
|
+ retval = ext4_ind_map_blocks(NULL, inode, map,
|
|
|
+ EXT4_GET_BLOCKS_NO_PUT_HOLE);
|
|
|
|
|
|
+add_delayed:
|
|
|
if (retval == 0) {
|
|
|
int ret;
|
|
|
/*
|