diff options
author | Zheng Liu <wenqing.lz@taobao.com> | 2012-11-08 21:57:32 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-11-08 21:57:32 -0500 |
commit | 51865fda28e585bdcc164474ff6438a9ccdbfada (patch) | |
tree | c4450c21bdbce0750543d8b1cd59992fb342a650 /fs/ext4 | |
parent | 9a26b66175e1c221f39bbe09e2e1d0a31a14ba6d (diff) |
ext4: let ext4 maintain extent status tree
This patch lets ext4 maintain extent status tree.
Currently it only tracks delay extent status in extent status tree. When a
delay allocation is issued, the related delay extent will be inserted into
extent status tree. When a delay extent is written out or invalidated, it will
be removed from this tree.
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 4 | ||||
-rw-r--r-- | fs/ext4/indirect.c | 1 | ||||
-rw-r--r-- | fs/ext4/inode.c | 38 | ||||
-rw-r--r-- | fs/ext4/super.c | 12 |
4 files changed, 51 insertions, 4 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index dce97de6a409..67660fa2a7e6 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -4344,6 +4344,8 @@ void ext4_ext_truncate(struct inode *inode) | |||
4344 | 4344 | ||
4345 | last_block = (inode->i_size + sb->s_blocksize - 1) | 4345 | last_block = (inode->i_size + sb->s_blocksize - 1) |
4346 | >> EXT4_BLOCK_SIZE_BITS(sb); | 4346 | >> EXT4_BLOCK_SIZE_BITS(sb); |
4347 | err = ext4_es_remove_extent(inode, last_block, | ||
4348 | EXT_MAX_BLOCKS - last_block); | ||
4347 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); | 4349 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); |
4348 | 4350 | ||
4349 | /* In a multi-transaction truncate, we only make the final | 4351 | /* In a multi-transaction truncate, we only make the final |
@@ -4971,6 +4973,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) | |||
4971 | ext4_ext_invalidate_cache(inode); | 4973 | ext4_ext_invalidate_cache(inode); |
4972 | ext4_discard_preallocations(inode); | 4974 | ext4_discard_preallocations(inode); |
4973 | 4975 | ||
4976 | err = ext4_es_remove_extent(inode, first_block, | ||
4977 | stop_block - first_block); | ||
4974 | err = ext4_ext_remove_space(inode, first_block, stop_block - 1); | 4978 | err = ext4_ext_remove_space(inode, first_block, stop_block - 1); |
4975 | 4979 | ||
4976 | ext4_ext_invalidate_cache(inode); | 4980 | ext4_ext_invalidate_cache(inode); |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 292337f27c9c..f6663c3a946d 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
@@ -1411,6 +1411,7 @@ void ext4_ind_truncate(struct inode *inode) | |||
1411 | down_write(&ei->i_data_sem); | 1411 | down_write(&ei->i_data_sem); |
1412 | 1412 | ||
1413 | ext4_discard_preallocations(inode); | 1413 | ext4_discard_preallocations(inode); |
1414 | ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block); | ||
1414 | 1415 | ||
1415 | /* | 1416 | /* |
1416 | * The orphan list entry will now protect us from any crash which | 1417 | * The orphan list entry will now protect us from any crash which |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f84bfd6d1867..1e92349272e0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -574,7 +574,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
574 | up_read((&EXT4_I(inode)->i_data_sem)); | 574 | up_read((&EXT4_I(inode)->i_data_sem)); |
575 | 575 | ||
576 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { | 576 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
577 | int ret = check_block_validity(inode, map); | 577 | int ret; |
578 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) { | ||
579 | /* delayed alloc may be allocated by fallocate and | ||
580 | * coverted to initialized by directIO. | ||
581 | * we need to handle delayed extent here. | ||
582 | */ | ||
583 | down_write((&EXT4_I(inode)->i_data_sem)); | ||
584 | goto delayed_mapped; | ||
585 | } | ||
586 | ret = check_block_validity(inode, map); | ||
578 | if (ret != 0) | 587 | if (ret != 0) |
579 | return ret; | 588 | return ret; |
580 | } | 589 | } |
@@ -656,8 +665,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
656 | * set the BH_Da_Mapped bit on them. Its important to do this | 665 | * set the BH_Da_Mapped bit on them. Its important to do this |
657 | * under the protection of i_data_sem. | 666 | * under the protection of i_data_sem. |
658 | */ | 667 | */ |
659 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) | 668 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
669 | int ret; | ||
660 | set_buffers_da_mapped(inode, map); | 670 | set_buffers_da_mapped(inode, map); |
671 | delayed_mapped: | ||
672 | /* delayed allocation blocks has been allocated */ | ||
673 | ret = ext4_es_remove_extent(inode, map->m_lblk, | ||
674 | map->m_len); | ||
675 | if (ret < 0) | ||
676 | retval = ret; | ||
677 | } | ||
661 | } | 678 | } |
662 | 679 | ||
663 | up_write((&EXT4_I(inode)->i_data_sem)); | 680 | up_write((&EXT4_I(inode)->i_data_sem)); |
@@ -1303,6 +1320,7 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1303 | struct inode *inode = page->mapping->host; | 1320 | struct inode *inode = page->mapping->host; |
1304 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1321 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
1305 | int num_clusters; | 1322 | int num_clusters; |
1323 | ext4_fsblk_t lblk; | ||
1306 | 1324 | ||
1307 | head = page_buffers(page); | 1325 | head = page_buffers(page); |
1308 | bh = head; | 1326 | bh = head; |
@@ -1317,11 +1335,15 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1317 | curr_off = next_off; | 1335 | curr_off = next_off; |
1318 | } while ((bh = bh->b_this_page) != head); | 1336 | } while ((bh = bh->b_this_page) != head); |
1319 | 1337 | ||
1338 | if (to_release) { | ||
1339 | lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
1340 | ext4_es_remove_extent(inode, lblk, to_release); | ||
1341 | } | ||
1342 | |||
1320 | /* If we have released all the blocks belonging to a cluster, then we | 1343 | /* If we have released all the blocks belonging to a cluster, then we |
1321 | * need to release the reserved space for that cluster. */ | 1344 | * need to release the reserved space for that cluster. */ |
1322 | num_clusters = EXT4_NUM_B2C(sbi, to_release); | 1345 | num_clusters = EXT4_NUM_B2C(sbi, to_release); |
1323 | while (num_clusters > 0) { | 1346 | while (num_clusters > 0) { |
1324 | ext4_fsblk_t lblk; | ||
1325 | lblk = (page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits)) + | 1347 | lblk = (page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits)) + |
1326 | ((num_clusters - 1) << sbi->s_cluster_bits); | 1348 | ((num_clusters - 1) << sbi->s_cluster_bits); |
1327 | if (sbi->s_cluster_ratio == 1 || | 1349 | if (sbi->s_cluster_ratio == 1 || |
@@ -1502,9 +1524,15 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) | |||
1502 | struct pagevec pvec; | 1524 | struct pagevec pvec; |
1503 | struct inode *inode = mpd->inode; | 1525 | struct inode *inode = mpd->inode; |
1504 | struct address_space *mapping = inode->i_mapping; | 1526 | struct address_space *mapping = inode->i_mapping; |
1527 | ext4_lblk_t start, last; | ||
1505 | 1528 | ||
1506 | index = mpd->first_page; | 1529 | index = mpd->first_page; |
1507 | end = mpd->next_page - 1; | 1530 | end = mpd->next_page - 1; |
1531 | |||
1532 | start = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
1533 | last = end << (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
1534 | ext4_es_remove_extent(inode, start, last - start + 1); | ||
1535 | |||
1508 | while (index <= end) { | 1536 | while (index <= end) { |
1509 | nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); | 1537 | nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); |
1510 | if (nr_pages == 0) | 1538 | if (nr_pages == 0) |
@@ -1816,6 +1844,10 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, | |||
1816 | goto out_unlock; | 1844 | goto out_unlock; |
1817 | } | 1845 | } |
1818 | 1846 | ||
1847 | retval = ext4_es_insert_extent(inode, map->m_lblk, map->m_len); | ||
1848 | if (retval) | ||
1849 | goto out_unlock; | ||
1850 | |||
1819 | /* Clear EXT4_MAP_FROM_CLUSTER flag since its purpose is served | 1851 | /* Clear EXT4_MAP_FROM_CLUSTER flag since its purpose is served |
1820 | * and it should not appear on the bh->b_state. | 1852 | * and it should not appear on the bh->b_state. |
1821 | */ | 1853 | */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 6791d091fbc7..ad6cd8aeb946 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include "xattr.h" | 50 | #include "xattr.h" |
51 | #include "acl.h" | 51 | #include "acl.h" |
52 | #include "mballoc.h" | 52 | #include "mballoc.h" |
53 | #include "ext4_extents.h" | ||
53 | 54 | ||
54 | #define CREATE_TRACE_POINTS | 55 | #define CREATE_TRACE_POINTS |
55 | #include <trace/events/ext4.h> | 56 | #include <trace/events/ext4.h> |
@@ -1033,6 +1034,7 @@ void ext4_clear_inode(struct inode *inode) | |||
1033 | clear_inode(inode); | 1034 | clear_inode(inode); |
1034 | dquot_drop(inode); | 1035 | dquot_drop(inode); |
1035 | ext4_discard_preallocations(inode); | 1036 | ext4_discard_preallocations(inode); |
1037 | ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); | ||
1036 | if (EXT4_I(inode)->jinode) { | 1038 | if (EXT4_I(inode)->jinode) { |
1037 | jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode), | 1039 | jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode), |
1038 | EXT4_I(inode)->jinode); | 1040 | EXT4_I(inode)->jinode); |
@@ -5296,9 +5298,14 @@ static int __init ext4_init_fs(void) | |||
5296 | init_waitqueue_head(&ext4__ioend_wq[i]); | 5298 | init_waitqueue_head(&ext4__ioend_wq[i]); |
5297 | } | 5299 | } |
5298 | 5300 | ||
5299 | err = ext4_init_pageio(); | 5301 | err = ext4_init_es(); |
5300 | if (err) | 5302 | if (err) |
5301 | return err; | 5303 | return err; |
5304 | |||
5305 | err = ext4_init_pageio(); | ||
5306 | if (err) | ||
5307 | goto out7; | ||
5308 | |||
5302 | err = ext4_init_system_zone(); | 5309 | err = ext4_init_system_zone(); |
5303 | if (err) | 5310 | if (err) |
5304 | goto out6; | 5311 | goto out6; |
@@ -5348,6 +5355,9 @@ out5: | |||
5348 | ext4_exit_system_zone(); | 5355 | ext4_exit_system_zone(); |
5349 | out6: | 5356 | out6: |
5350 | ext4_exit_pageio(); | 5357 | ext4_exit_pageio(); |
5358 | out7: | ||
5359 | ext4_exit_es(); | ||
5360 | |||
5351 | return err; | 5361 | return err; |
5352 | } | 5362 | } |
5353 | 5363 | ||