Commit c5d02785 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs: inherit mtime of original block during GC

Don't let f2fs inner GC ruins original aging degree of segment.
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 6f3a01ae
...@@ -1416,7 +1416,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) ...@@ -1416,7 +1416,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
old_blkaddr = dn->data_blkaddr; old_blkaddr = dn->data_blkaddr;
f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
&sum, seg_type, NULL); &sum, seg_type, NULL, false);
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
invalidate_mapping_pages(META_MAPPING(sbi), invalidate_mapping_pages(META_MAPPING(sbi),
old_blkaddr, old_blkaddr); old_blkaddr, old_blkaddr);
......
...@@ -3357,7 +3357,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn, ...@@ -3357,7 +3357,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
int f2fs_inplace_write_data(struct f2fs_io_info *fio); int f2fs_inplace_write_data(struct f2fs_io_info *fio);
void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
block_t old_blkaddr, block_t new_blkaddr, block_t old_blkaddr, block_t new_blkaddr,
bool recover_curseg, bool recover_newaddr); bool recover_curseg, bool recover_newaddr,
bool from_gc);
void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
block_t old_addr, block_t new_addr, block_t old_addr, block_t new_addr,
unsigned char version, bool recover_curseg, unsigned char version, bool recover_curseg,
...@@ -3365,7 +3366,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, ...@@ -3365,7 +3366,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr, block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type, struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio); struct f2fs_io_info *fio, bool from_gc);
void f2fs_wait_on_page_writeback(struct page *page, void f2fs_wait_on_page_writeback(struct page *page,
enum page_type type, bool ordered, bool locked); enum page_type type, bool ordered, bool locked);
void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr); void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr);
......
...@@ -879,7 +879,7 @@ static int move_data_block(struct inode *inode, block_t bidx, ...@@ -879,7 +879,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
} }
f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr, f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
&sum, CURSEG_COLD_DATA, NULL); &sum, CURSEG_COLD_DATA, NULL, true);
fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi), fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS); newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
...@@ -929,7 +929,7 @@ static int move_data_block(struct inode *inode, block_t bidx, ...@@ -929,7 +929,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
recover_block: recover_block:
if (err) if (err)
f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr, f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
true, true); true, true, true);
up_out: up_out:
if (lfs_mode) if (lfs_mode)
up_write(&fio.sbi->io_order_lock); up_write(&fio.sbi->io_order_lock);
......
...@@ -2154,11 +2154,28 @@ static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type, ...@@ -2154,11 +2154,28 @@ static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
__mark_sit_entry_dirty(sbi, segno); __mark_sit_entry_dirty(sbi, segno);
} }
static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr) static inline unsigned long long get_segment_mtime(struct f2fs_sb_info *sbi,
block_t blkaddr)
{ {
unsigned int segno = GET_SEGNO(sbi, blkaddr); unsigned int segno = GET_SEGNO(sbi, blkaddr);
struct seg_entry *se = get_seg_entry(sbi, segno);
unsigned long long mtime = get_mtime(sbi, false); if (segno == NULL_SEGNO)
return 0;
return get_seg_entry(sbi, segno)->mtime;
}
static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr,
unsigned long long old_mtime)
{
struct seg_entry *se;
unsigned int segno = GET_SEGNO(sbi, blkaddr);
unsigned long long ctime = get_mtime(sbi, false);
unsigned long long mtime = old_mtime ? old_mtime : ctime;
if (segno == NULL_SEGNO)
return;
se = get_seg_entry(sbi, segno);
if (!se->mtime) if (!se->mtime)
se->mtime = mtime; se->mtime = mtime;
...@@ -2166,8 +2183,8 @@ static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr) ...@@ -2166,8 +2183,8 @@ static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr)
se->mtime = div_u64(se->mtime * se->valid_blocks + mtime, se->mtime = div_u64(se->mtime * se->valid_blocks + mtime,
se->valid_blocks + 1); se->valid_blocks + 1);
if (mtime > SIT_I(sbi)->max_mtime) if (ctime > SIT_I(sbi)->max_mtime)
SIT_I(sbi)->max_mtime = mtime; SIT_I(sbi)->max_mtime = ctime;
} }
static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
...@@ -2189,8 +2206,6 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) ...@@ -2189,8 +2206,6 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
f2fs_bug_on(sbi, (new_vblocks < 0 || f2fs_bug_on(sbi, (new_vblocks < 0 ||
(new_vblocks > f2fs_usable_blks_in_seg(sbi, segno)))); (new_vblocks > f2fs_usable_blks_in_seg(sbi, segno))));
update_segment_mtime(sbi, blkaddr);
se->valid_blocks = new_vblocks; se->valid_blocks = new_vblocks;
/* Update valid block bitmap */ /* Update valid block bitmap */
...@@ -2284,6 +2299,7 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) ...@@ -2284,6 +2299,7 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
/* add it into sit main buffer */ /* add it into sit main buffer */
down_write(&sit_i->sentry_lock); down_write(&sit_i->sentry_lock);
update_segment_mtime(sbi, addr, 0);
update_sit_entry(sbi, addr, -1); update_sit_entry(sbi, addr, -1);
/* add it into dirty seglist */ /* add it into dirty seglist */
...@@ -3192,10 +3208,11 @@ static int __get_segment_type(struct f2fs_io_info *fio) ...@@ -3192,10 +3208,11 @@ static int __get_segment_type(struct f2fs_io_info *fio)
void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr, block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type, struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio) struct f2fs_io_info *fio, bool from_gc)
{ {
struct sit_info *sit_i = SIT_I(sbi); struct sit_info *sit_i = SIT_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, type); struct curseg_info *curseg = CURSEG_I(sbi, type);
unsigned long long old_mtime;
down_read(&SM_I(sbi)->curseg_lock); down_read(&SM_I(sbi)->curseg_lock);
...@@ -3217,6 +3234,14 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, ...@@ -3217,6 +3234,14 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
stat_inc_block_count(sbi, curseg); stat_inc_block_count(sbi, curseg);
if (from_gc) {
old_mtime = get_segment_mtime(sbi, old_blkaddr);
} else {
update_segment_mtime(sbi, old_blkaddr, 0);
old_mtime = 0;
}
update_segment_mtime(sbi, *new_blkaddr, old_mtime);
/* /*
* SIT information should be updated before segment allocation, * SIT information should be updated before segment allocation,
* since SSR needs latest valid block information. * since SSR needs latest valid block information.
...@@ -3293,7 +3318,8 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) ...@@ -3293,7 +3318,8 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
down_read(&fio->sbi->io_order_lock); down_read(&fio->sbi->io_order_lock);
reallocate: reallocate:
f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
&fio->new_blkaddr, sum, type, fio); &fio->new_blkaddr, sum, type, fio,
is_cold_data(fio->page));
if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO) if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
invalidate_mapping_pages(META_MAPPING(fio->sbi), invalidate_mapping_pages(META_MAPPING(fio->sbi),
fio->old_blkaddr, fio->old_blkaddr); fio->old_blkaddr, fio->old_blkaddr);
...@@ -3409,7 +3435,8 @@ static inline int __f2fs_get_curseg(struct f2fs_sb_info *sbi, ...@@ -3409,7 +3435,8 @@ static inline int __f2fs_get_curseg(struct f2fs_sb_info *sbi,
void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
block_t old_blkaddr, block_t new_blkaddr, block_t old_blkaddr, block_t new_blkaddr,
bool recover_curseg, bool recover_newaddr) bool recover_curseg, bool recover_newaddr,
bool from_gc)
{ {
struct sit_info *sit_i = SIT_I(sbi); struct sit_info *sit_i = SIT_I(sbi);
struct curseg_info *curseg; struct curseg_info *curseg;
...@@ -3460,11 +3487,16 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, ...@@ -3460,11 +3487,16 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr); curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
__add_sum_entry(sbi, type, sum); __add_sum_entry(sbi, type, sum);
if (!recover_curseg || recover_newaddr) if (!recover_curseg || recover_newaddr) {
if (!from_gc)
update_segment_mtime(sbi, new_blkaddr, 0);
update_sit_entry(sbi, new_blkaddr, 1); update_sit_entry(sbi, new_blkaddr, 1);
}
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) { if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) {
invalidate_mapping_pages(META_MAPPING(sbi), invalidate_mapping_pages(META_MAPPING(sbi),
old_blkaddr, old_blkaddr); old_blkaddr, old_blkaddr);
if (!from_gc)
update_segment_mtime(sbi, old_blkaddr, 0);
update_sit_entry(sbi, old_blkaddr, -1); update_sit_entry(sbi, old_blkaddr, -1);
} }
...@@ -3496,7 +3528,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, ...@@ -3496,7 +3528,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
set_summary(&sum, dn->nid, dn->ofs_in_node, version); set_summary(&sum, dn->nid, dn->ofs_in_node, version);
f2fs_do_replace_block(sbi, &sum, old_addr, new_addr, f2fs_do_replace_block(sbi, &sum, old_addr, new_addr,
recover_curseg, recover_newaddr); recover_curseg, recover_newaddr, false);
f2fs_update_data_blkaddr(dn, new_addr); f2fs_update_data_blkaddr(dn, new_addr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment