aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorZheng Liu <wenqing.lz@taobao.com>2012-11-08 21:57:32 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-11-08 21:57:32 -0500
commit51865fda28e585bdcc164474ff6438a9ccdbfada (patch)
treec4450c21bdbce0750543d8b1cd59992fb342a650 /fs/ext4
parent9a26b66175e1c221f39bbe09e2e1d0a31a14ba6d (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.c4
-rw-r--r--fs/ext4/indirect.c1
-rw-r--r--fs/ext4/inode.c38
-rw-r--r--fs/ext4/super.c12
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);
671delayed_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();
5349out6: 5356out6:
5350 ext4_exit_pageio(); 5357 ext4_exit_pageio();
5358out7:
5359 ext4_exit_es();
5360
5351 return err; 5361 return err;
5352} 5362}
5353 5363