diff options
Diffstat (limited to 'fs/ext4/extents_status.c')
-rw-r--r-- | fs/ext4/extents_status.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 30596498ed0b..e04d45733976 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
@@ -382,7 +382,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) | |||
382 | static int ext4_es_can_be_merged(struct extent_status *es1, | 382 | static int ext4_es_can_be_merged(struct extent_status *es1, |
383 | struct extent_status *es2) | 383 | struct extent_status *es2) |
384 | { | 384 | { |
385 | if (ext4_es_status(es1) != ext4_es_status(es2)) | 385 | if (ext4_es_type(es1) != ext4_es_type(es2)) |
386 | return 0; | 386 | return 0; |
387 | 387 | ||
388 | if (((__u64) es1->es_len) + es2->es_len > EXT_MAX_BLOCKS) { | 388 | if (((__u64) es1->es_len) + es2->es_len > EXT_MAX_BLOCKS) { |
@@ -425,6 +425,8 @@ ext4_es_try_to_merge_left(struct inode *inode, struct extent_status *es) | |||
425 | es1 = rb_entry(node, struct extent_status, rb_node); | 425 | es1 = rb_entry(node, struct extent_status, rb_node); |
426 | if (ext4_es_can_be_merged(es1, es)) { | 426 | if (ext4_es_can_be_merged(es1, es)) { |
427 | es1->es_len += es->es_len; | 427 | es1->es_len += es->es_len; |
428 | if (ext4_es_is_referenced(es)) | ||
429 | ext4_es_set_referenced(es1); | ||
428 | rb_erase(&es->rb_node, &tree->root); | 430 | rb_erase(&es->rb_node, &tree->root); |
429 | ext4_es_free_extent(inode, es); | 431 | ext4_es_free_extent(inode, es); |
430 | es = es1; | 432 | es = es1; |
@@ -447,6 +449,8 @@ ext4_es_try_to_merge_right(struct inode *inode, struct extent_status *es) | |||
447 | es1 = rb_entry(node, struct extent_status, rb_node); | 449 | es1 = rb_entry(node, struct extent_status, rb_node); |
448 | if (ext4_es_can_be_merged(es, es1)) { | 450 | if (ext4_es_can_be_merged(es, es1)) { |
449 | es->es_len += es1->es_len; | 451 | es->es_len += es1->es_len; |
452 | if (ext4_es_is_referenced(es1)) | ||
453 | ext4_es_set_referenced(es); | ||
450 | rb_erase(node, &tree->root); | 454 | rb_erase(node, &tree->root); |
451 | ext4_es_free_extent(inode, es1); | 455 | ext4_es_free_extent(inode, es1); |
452 | } | 456 | } |
@@ -813,6 +817,8 @@ out: | |||
813 | es->es_lblk = es1->es_lblk; | 817 | es->es_lblk = es1->es_lblk; |
814 | es->es_len = es1->es_len; | 818 | es->es_len = es1->es_len; |
815 | es->es_pblk = es1->es_pblk; | 819 | es->es_pblk = es1->es_pblk; |
820 | if (!ext4_es_is_referenced(es)) | ||
821 | ext4_es_set_referenced(es); | ||
816 | stats->es_stats_cache_hits++; | 822 | stats->es_stats_cache_hits++; |
817 | } else { | 823 | } else { |
818 | stats->es_stats_cache_misses++; | 824 | stats->es_stats_cache_misses++; |
@@ -1252,11 +1258,17 @@ static int es_do_reclaim_extents(struct ext4_inode_info *ei, ext4_lblk_t end, | |||
1252 | * We can't reclaim delayed extent from status tree because | 1258 | * We can't reclaim delayed extent from status tree because |
1253 | * fiemap, bigallic, and seek_data/hole need to use it. | 1259 | * fiemap, bigallic, and seek_data/hole need to use it. |
1254 | */ | 1260 | */ |
1255 | if (!ext4_es_is_delayed(es)) { | 1261 | if (ext4_es_is_delayed(es)) |
1256 | rb_erase(&es->rb_node, &tree->root); | 1262 | goto next; |
1257 | ext4_es_free_extent(inode, es); | 1263 | if (ext4_es_is_referenced(es)) { |
1258 | (*nr_shrunk)++; | 1264 | ext4_es_clear_referenced(es); |
1265 | goto next; | ||
1259 | } | 1266 | } |
1267 | |||
1268 | rb_erase(&es->rb_node, &tree->root); | ||
1269 | ext4_es_free_extent(inode, es); | ||
1270 | (*nr_shrunk)++; | ||
1271 | next: | ||
1260 | if (!node) | 1272 | if (!node) |
1261 | goto out_wrap; | 1273 | goto out_wrap; |
1262 | es = rb_entry(node, struct extent_status, rb_node); | 1274 | es = rb_entry(node, struct extent_status, rb_node); |