|
|
|
@@ -2154,11 +2154,28 @@ static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
|
|
|
|
|
__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);
|
|
|
|
|
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)
|
|
|
|
|
se->mtime = mtime;
|
|
|
|
@@ -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->valid_blocks + 1);
|
|
|
|
|
|
|
|
|
|
if (mtime > SIT_I(sbi)->max_mtime)
|
|
|
|
|
SIT_I(sbi)->max_mtime = mtime;
|
|
|
|
|
if (ctime > SIT_I(sbi)->max_mtime)
|
|
|
|
|
SIT_I(sbi)->max_mtime = ctime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 ||
|
|
|
|
|
(new_vblocks > f2fs_usable_blks_in_seg(sbi, segno))));
|
|
|
|
|
|
|
|
|
|
update_segment_mtime(sbi, blkaddr);
|
|
|
|
|
|
|
|
|
|
se->valid_blocks = new_vblocks;
|
|
|
|
|
|
|
|
|
|
/* Update valid block bitmap */
|
|
|
|
@@ -2284,6 +2299,7 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
|
|
|
|
|
/* add it into sit main buffer */
|
|
|
|
|
down_write(&sit_i->sentry_lock);
|
|
|
|
|
|
|
|
|
|
update_segment_mtime(sbi, addr, 0);
|
|
|
|
|
update_sit_entry(sbi, addr, -1);
|
|
|
|
|
|
|
|
|
|
/* add it into dirty seglist */
|
|
|
|
@@ -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,
|
|
|
|
|
block_t old_blkaddr, block_t *new_blkaddr,
|
|
|
|
|
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 curseg_info *curseg = CURSEG_I(sbi, type);
|
|
|
|
|
unsigned long long old_mtime;
|
|
|
|
|
|
|
|
|
|
down_read(&SM_I(sbi)->curseg_lock);
|
|
|
|
|
|
|
|
|
@@ -3217,6 +3234,14 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
* 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)
|
|
|
|
|
down_read(&fio->sbi->io_order_lock);
|
|
|
|
|
reallocate:
|
|
|
|
|
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)
|
|
|
|
|
invalidate_mapping_pages(META_MAPPING(fio->sbi),
|
|
|
|
|
fio->old_blkaddr, fio->old_blkaddr);
|
|
|
|
@@ -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,
|
|
|
|
|
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 curseg_info *curseg;
|
|
|
|
@@ -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);
|
|
|
|
|
__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);
|
|
|
|
|
}
|
|
|
|
|
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) {
|
|
|
|
|
invalidate_mapping_pages(META_MAPPING(sbi),
|
|
|
|
|
old_blkaddr, old_blkaddr);
|
|
|
|
|
if (!from_gc)
|
|
|
|
|
update_segment_mtime(sbi, old_blkaddr, 0);
|
|
|
|
|
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,
|
|
|
|
|
set_summary(&sum, dn->nid, dn->ofs_in_node, version);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|