From 107a7bd31ac003e42c0f966aa8e5b26947de6024 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 16 Aug 2013 21:23:41 -0400 Subject: ext4: cache all of an extent tree's leaf block upon reading When we read in an extent tree leaf block from disk, arrange to have all of its entries cached. In nearly all cases the in-memory representation will be more compact than the on-disk representation in the buffer cache, and it allows us to get the information without having to traverse the extent tree for successive extents. Signed-off-by: "Theodore Ts'o" Reviewed-by: Zheng Liu --- fs/ext4/extents_status.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'fs/ext4/extents_status.c') diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index ded2615b63e0..1dc5df016e25 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -419,7 +419,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, unsigned short ee_len; int depth, ee_status, es_status; - path = ext4_ext_find_extent(inode, es->es_lblk, NULL); + path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE); if (IS_ERR(path)) return; @@ -683,6 +683,41 @@ error: return err; } +/* + * ext4_es_cache_extent() inserts information into the extent status + * tree if and only if there isn't information about the range in + * question already. + */ +void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk, + ext4_lblk_t len, ext4_fsblk_t pblk, + unsigned int status) +{ + struct extent_status *es; + struct extent_status newes; + ext4_lblk_t end = lblk + len - 1; + + newes.es_lblk = lblk; + newes.es_len = len; + ext4_es_store_pblock(&newes, pblk); + ext4_es_store_status(&newes, status); + trace_ext4_es_cache_extent(inode, &newes); + + if (!len) + return; + + BUG_ON(end < lblk); + + write_lock(&EXT4_I(inode)->i_es_lock); + + es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk); + if (es && ((es->es_lblk <= lblk) || (es->es_lblk <= end))) + goto out; + + __es_insert_extent(inode, &newes); +out: + write_unlock(&EXT4_I(inode)->i_es_lock); +} + /* * ext4_es_lookup_extent() looks up an extent in extent status tree. * -- cgit v1.2.3