f2fs: introduce inmem curseg
Previous implementation of aligned pinfile allocation will: - allocate new segment on cold data log no matter whether last used segment is partially used or not, it makes IOs more random; - force concurrent cold data/GCed IO going into warm data area, it can make a bad effect on hot/cold data separation; In this patch, we introduce a new type of log named 'inmem curseg', the differents from normal curseg is: - it reuses existed segment type (CURSEG_XXX_NODE/DATA); - it only exists in memory, its segno, blkofs, summary will not b persisted into checkpoint area; With this new feature, we can enhance scalability of log, special allocators can be created for purposes: - pure lfs allocator for aligned pinfile allocation or file defragmentation - pure ssr allocator for later feature So that, let's update aligned pinfile allocation to use this new inmem curseg fwk. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
376207af4b
commit
d0b9e42ab6
8 changed files with 113 additions and 52 deletions
|
@ -1619,11 +1619,16 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
|
||||||
|
|
||||||
f2fs_flush_sit_entries(sbi, cpc);
|
f2fs_flush_sit_entries(sbi, cpc);
|
||||||
|
|
||||||
|
/* save inmem log status */
|
||||||
|
f2fs_save_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
|
||||||
|
|
||||||
err = do_checkpoint(sbi, cpc);
|
err = do_checkpoint(sbi, cpc);
|
||||||
if (err)
|
if (err)
|
||||||
f2fs_release_discard_addrs(sbi);
|
f2fs_release_discard_addrs(sbi);
|
||||||
else
|
else
|
||||||
f2fs_clear_prefree_segments(sbi, cpc);
|
f2fs_clear_prefree_segments(sbi, cpc);
|
||||||
|
|
||||||
|
f2fs_restore_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
|
||||||
stop:
|
stop:
|
||||||
unblock_operations(sbi);
|
unblock_operations(sbi);
|
||||||
stat_inc_cp_count(sbi->stat_info);
|
stat_inc_cp_count(sbi->stat_info);
|
||||||
|
@ -1654,7 +1659,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
|
||||||
}
|
}
|
||||||
|
|
||||||
sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
|
sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
|
||||||
NR_CURSEG_TYPE - __cp_payload(sbi)) *
|
NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
|
||||||
F2FS_ORPHANS_PER_BLOCK;
|
F2FS_ORPHANS_PER_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
|
||||||
* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
|
* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
|
||||||
/ 2;
|
/ 2;
|
||||||
si->util_invalid = 50 - si->util_free - si->util_valid;
|
si->util_invalid = 50 - si->util_free - si->util_valid;
|
||||||
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
|
for (i = CURSEG_HOT_DATA; i < NO_CHECK_TYPE; i++) {
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, i);
|
struct curseg_info *curseg = CURSEG_I(sbi, i);
|
||||||
si->curseg[i] = curseg->segno;
|
si->curseg[i] = curseg->segno;
|
||||||
si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno);
|
si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno);
|
||||||
|
@ -393,6 +393,10 @@ static int stat_show(struct seq_file *s, void *v)
|
||||||
si->dirty_seg[CURSEG_COLD_NODE],
|
si->dirty_seg[CURSEG_COLD_NODE],
|
||||||
si->full_seg[CURSEG_COLD_NODE],
|
si->full_seg[CURSEG_COLD_NODE],
|
||||||
si->valid_blks[CURSEG_COLD_NODE]);
|
si->valid_blks[CURSEG_COLD_NODE]);
|
||||||
|
seq_printf(s, " - Pinned file: %8d %8d %8d\n",
|
||||||
|
si->curseg[CURSEG_COLD_DATA_PINNED],
|
||||||
|
si->cursec[CURSEG_COLD_DATA_PINNED],
|
||||||
|
si->curzone[CURSEG_COLD_DATA_PINNED]);
|
||||||
seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
|
seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
|
||||||
si->main_area_segs - si->dirty_count -
|
si->main_area_segs - si->dirty_count -
|
||||||
si->prefree_count - si->free_segs,
|
si->prefree_count - si->free_segs,
|
||||||
|
|
|
@ -973,7 +973,9 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
|
||||||
*/
|
*/
|
||||||
#define NR_CURSEG_DATA_TYPE (3)
|
#define NR_CURSEG_DATA_TYPE (3)
|
||||||
#define NR_CURSEG_NODE_TYPE (3)
|
#define NR_CURSEG_NODE_TYPE (3)
|
||||||
#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
|
#define NR_CURSEG_INMEM_TYPE (1)
|
||||||
|
#define NR_CURSEG_PERSIST_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
|
||||||
|
#define NR_CURSEG_TYPE (NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CURSEG_HOT_DATA = 0, /* directory entry blocks */
|
CURSEG_HOT_DATA = 0, /* directory entry blocks */
|
||||||
|
@ -982,8 +984,10 @@ enum {
|
||||||
CURSEG_HOT_NODE, /* direct node blocks of directory files */
|
CURSEG_HOT_NODE, /* direct node blocks of directory files */
|
||||||
CURSEG_WARM_NODE, /* direct node blocks of normal files */
|
CURSEG_WARM_NODE, /* direct node blocks of normal files */
|
||||||
CURSEG_COLD_NODE, /* indirect node blocks */
|
CURSEG_COLD_NODE, /* indirect node blocks */
|
||||||
NO_CHECK_TYPE,
|
NR_PERSISTENT_LOG, /* number of persistent log */
|
||||||
CURSEG_COLD_DATA_PINNED,/* cold data for pinned file */
|
CURSEG_COLD_DATA_PINNED = NR_PERSISTENT_LOG,
|
||||||
|
/* pinned file that needs consecutive block address */
|
||||||
|
NO_CHECK_TYPE, /* number of persistent & inmem log */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct flush_cmd {
|
struct flush_cmd {
|
||||||
|
@ -3333,6 +3337,8 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
|
||||||
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
|
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
|
||||||
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
|
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
|
||||||
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
|
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
|
||||||
|
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type);
|
||||||
|
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type);
|
||||||
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
|
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
|
||||||
unsigned int start, unsigned int end);
|
unsigned int start, unsigned int end);
|
||||||
void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);
|
void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);
|
||||||
|
|
|
@ -1656,13 +1656,14 @@ next_alloc:
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(&sbi->pin_sem);
|
down_write(&sbi->pin_sem);
|
||||||
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
|
|
||||||
|
|
||||||
f2fs_lock_op(sbi);
|
f2fs_lock_op(sbi);
|
||||||
f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA);
|
f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED);
|
||||||
f2fs_unlock_op(sbi);
|
f2fs_unlock_op(sbi);
|
||||||
|
|
||||||
|
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
|
||||||
err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);
|
err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);
|
||||||
|
|
||||||
up_write(&sbi->pin_sem);
|
up_write(&sbi->pin_sem);
|
||||||
|
|
||||||
done += map.m_len;
|
done += map.m_len;
|
||||||
|
|
|
@ -1463,7 +1463,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
|
||||||
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
|
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
|
||||||
|
|
||||||
/* Move out cursegs from the target range */
|
/* Move out cursegs from the target range */
|
||||||
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_TYPE; type++)
|
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++)
|
||||||
f2fs_allocate_segment_for_resize(sbi, type, start, end);
|
f2fs_allocate_segment_for_resize(sbi, type, start, end);
|
||||||
|
|
||||||
/* do GC to move out valid blocks in the range */
|
/* do GC to move out valid blocks in the range */
|
||||||
|
|
|
@ -1962,7 +1962,7 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
|
||||||
|
|
||||||
mutex_lock(&dirty_i->seglist_lock);
|
mutex_lock(&dirty_i->seglist_lock);
|
||||||
for_each_set_bit(segno, dirty_i->dirty_segmap[PRE], MAIN_SEGS(sbi))
|
for_each_set_bit(segno, dirty_i->dirty_segmap[PRE], MAIN_SEGS(sbi))
|
||||||
__set_test_and_free(sbi, segno);
|
__set_test_and_free(sbi, segno, false);
|
||||||
mutex_unlock(&dirty_i->seglist_lock);
|
mutex_unlock(&dirty_i->seglist_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2500,6 +2500,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
struct summary_footer *sum_footer;
|
struct summary_footer *sum_footer;
|
||||||
|
|
||||||
|
curseg->inited = true;
|
||||||
curseg->segno = curseg->next_segno;
|
curseg->segno = curseg->next_segno;
|
||||||
curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
|
curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
|
||||||
curseg->next_blkoff = 0;
|
curseg->next_blkoff = 0;
|
||||||
|
@ -2507,24 +2508,31 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
|
||||||
|
|
||||||
sum_footer = &(curseg->sum_blk->footer);
|
sum_footer = &(curseg->sum_blk->footer);
|
||||||
memset(sum_footer, 0, sizeof(struct summary_footer));
|
memset(sum_footer, 0, sizeof(struct summary_footer));
|
||||||
if (IS_DATASEG(type))
|
if (IS_DATASEG(curseg->seg_type))
|
||||||
SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
|
SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
|
||||||
if (IS_NODESEG(type))
|
if (IS_NODESEG(curseg->seg_type))
|
||||||
SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
|
SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
|
||||||
__set_sit_entry_type(sbi, type, curseg->segno, modified);
|
__set_sit_entry_type(sbi, curseg->seg_type, curseg->segno, modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
|
static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
|
||||||
{
|
{
|
||||||
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
|
|
||||||
/* if segs_per_sec is large than 1, we need to keep original policy. */
|
/* if segs_per_sec is large than 1, we need to keep original policy. */
|
||||||
if (__is_large_section(sbi))
|
if (__is_large_section(sbi))
|
||||||
return CURSEG_I(sbi, type)->segno;
|
return curseg->segno;
|
||||||
|
|
||||||
|
/* inmem log may not locate on any segment after mount */
|
||||||
|
if (!curseg->inited)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
|
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (test_opt(sbi, NOHEAP) &&
|
if (test_opt(sbi, NOHEAP) &&
|
||||||
(type == CURSEG_HOT_DATA || IS_NODESEG(type)))
|
(curseg->seg_type == CURSEG_HOT_DATA ||
|
||||||
|
IS_NODESEG(curseg->seg_type)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (SIT_I(sbi)->last_victim[ALLOC_NEXT])
|
if (SIT_I(sbi)->last_victim[ALLOC_NEXT])
|
||||||
|
@ -2534,7 +2542,7 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
|
||||||
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)
|
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return CURSEG_I(sbi, type)->segno;
|
return curseg->segno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2544,12 +2552,14 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
|
||||||
static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
|
static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
|
||||||
{
|
{
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
|
unsigned short seg_type = curseg->seg_type;
|
||||||
unsigned int segno = curseg->segno;
|
unsigned int segno = curseg->segno;
|
||||||
int dir = ALLOC_LEFT;
|
int dir = ALLOC_LEFT;
|
||||||
|
|
||||||
write_sum_page(sbi, curseg->sum_blk,
|
if (curseg->inited)
|
||||||
|
write_sum_page(sbi, curseg->sum_blk,
|
||||||
GET_SUM_BLOCK(sbi, segno));
|
GET_SUM_BLOCK(sbi, segno));
|
||||||
if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
|
if (seg_type == CURSEG_WARM_DATA || seg_type == CURSEG_COLD_DATA)
|
||||||
dir = ALLOC_RIGHT;
|
dir = ALLOC_RIGHT;
|
||||||
|
|
||||||
if (test_opt(sbi, NOHEAP))
|
if (test_opt(sbi, NOHEAP))
|
||||||
|
@ -2626,6 +2636,43 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
|
||||||
f2fs_put_page(sum_page, 1);
|
f2fs_put_page(sum_page, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type)
|
||||||
|
{
|
||||||
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
|
|
||||||
|
mutex_lock(&curseg->curseg_mutex);
|
||||||
|
if (!curseg->inited)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (get_valid_blocks(sbi, curseg->segno, false)) {
|
||||||
|
write_sum_page(sbi, curseg->sum_blk,
|
||||||
|
GET_SUM_BLOCK(sbi, curseg->segno));
|
||||||
|
} else {
|
||||||
|
mutex_lock(&DIRTY_I(sbi)->seglist_lock);
|
||||||
|
__set_test_and_free(sbi, curseg->segno, true);
|
||||||
|
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
mutex_unlock(&curseg->curseg_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type)
|
||||||
|
{
|
||||||
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
|
|
||||||
|
mutex_lock(&curseg->curseg_mutex);
|
||||||
|
if (!curseg->inited)
|
||||||
|
goto out;
|
||||||
|
if (get_valid_blocks(sbi, curseg->segno, false))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
mutex_lock(&DIRTY_I(sbi)->seglist_lock);
|
||||||
|
__set_test_and_inuse(sbi, curseg->segno);
|
||||||
|
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
|
||||||
|
out:
|
||||||
|
mutex_unlock(&curseg->curseg_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
|
static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
|
||||||
{
|
{
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
|
@ -2742,11 +2789,15 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type)
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||||
unsigned int old_segno;
|
unsigned int old_segno;
|
||||||
|
|
||||||
|
if (!curseg->inited)
|
||||||
|
goto alloc;
|
||||||
|
|
||||||
if (!curseg->next_blkoff &&
|
if (!curseg->next_blkoff &&
|
||||||
!get_valid_blocks(sbi, curseg->segno, false) &&
|
!get_valid_blocks(sbi, curseg->segno, false) &&
|
||||||
!get_ckpt_valid_blocks(sbi, curseg->segno))
|
!get_ckpt_valid_blocks(sbi, curseg->segno))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
alloc:
|
||||||
old_segno = curseg->segno;
|
old_segno = curseg->segno;
|
||||||
SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true);
|
SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true);
|
||||||
locate_dirty_segment(sbi, old_segno);
|
locate_dirty_segment(sbi, old_segno);
|
||||||
|
@ -3130,19 +3181,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
||||||
{
|
{
|
||||||
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);
|
||||||
bool put_pin_sem = false;
|
|
||||||
|
|
||||||
if (type == CURSEG_COLD_DATA) {
|
|
||||||
/* GC during CURSEG_COLD_DATA_PINNED allocation */
|
|
||||||
if (down_read_trylock(&sbi->pin_sem)) {
|
|
||||||
put_pin_sem = true;
|
|
||||||
} else {
|
|
||||||
type = CURSEG_WARM_DATA;
|
|
||||||
curseg = CURSEG_I(sbi, type);
|
|
||||||
}
|
|
||||||
} else if (type == CURSEG_COLD_DATA_PINNED) {
|
|
||||||
type = CURSEG_COLD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
down_read(&SM_I(sbi)->curseg_lock);
|
down_read(&SM_I(sbi)->curseg_lock);
|
||||||
|
|
||||||
|
@ -3208,9 +3246,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
||||||
mutex_unlock(&curseg->curseg_mutex);
|
mutex_unlock(&curseg->curseg_mutex);
|
||||||
|
|
||||||
up_read(&SM_I(sbi)->curseg_lock);
|
up_read(&SM_I(sbi)->curseg_lock);
|
||||||
|
|
||||||
if (put_pin_sem)
|
|
||||||
up_read(&sbi->pin_sem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_device_state(struct f2fs_io_info *fio)
|
static void update_device_state(struct f2fs_io_info *fio)
|
||||||
|
@ -3578,7 +3613,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
|
||||||
blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
|
blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
|
||||||
CURSEG_HOT_DATA]);
|
CURSEG_HOT_DATA]);
|
||||||
if (__exist_node_summaries(sbi))
|
if (__exist_node_summaries(sbi))
|
||||||
blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
|
blk_addr = sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type);
|
||||||
else
|
else
|
||||||
blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
|
blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3656,8 +3691,9 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__exist_node_summaries(sbi))
|
if (__exist_node_summaries(sbi))
|
||||||
f2fs_ra_meta_pages(sbi, sum_blk_addr(sbi, NR_CURSEG_TYPE, type),
|
f2fs_ra_meta_pages(sbi,
|
||||||
NR_CURSEG_TYPE - type, META_CP, true);
|
sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type),
|
||||||
|
NR_CURSEG_PERSIST_TYPE - type, META_CP, true);
|
||||||
|
|
||||||
for (; type <= CURSEG_COLD_NODE; type++) {
|
for (; type <= CURSEG_COLD_NODE; type++) {
|
||||||
err = read_normal_summaries(sbi, type);
|
err = read_normal_summaries(sbi, type);
|
||||||
|
@ -4159,14 +4195,14 @@ static int build_curseg(struct f2fs_sb_info *sbi)
|
||||||
struct curseg_info *array;
|
struct curseg_info *array;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE, sizeof(*array)),
|
array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE,
|
||||||
GFP_KERNEL);
|
sizeof(*array)), GFP_KERNEL);
|
||||||
if (!array)
|
if (!array)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
SM_I(sbi)->curseg_array = array;
|
SM_I(sbi)->curseg_array = array;
|
||||||
|
|
||||||
for (i = 0; i < NR_CURSEG_TYPE; i++) {
|
for (i = 0; i < NO_CHECK_TYPE; i++) {
|
||||||
mutex_init(&array[i].curseg_mutex);
|
mutex_init(&array[i].curseg_mutex);
|
||||||
array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
|
array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
|
||||||
if (!array[i].sum_blk)
|
if (!array[i].sum_blk)
|
||||||
|
@ -4176,8 +4212,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
|
||||||
sizeof(struct f2fs_journal), GFP_KERNEL);
|
sizeof(struct f2fs_journal), GFP_KERNEL);
|
||||||
if (!array[i].journal)
|
if (!array[i].journal)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
if (i < NR_PERSISTENT_LOG)
|
||||||
|
array[i].seg_type = CURSEG_HOT_DATA + i;
|
||||||
|
else if (i == CURSEG_COLD_DATA_PINNED)
|
||||||
|
array[i].seg_type = CURSEG_COLD_DATA;
|
||||||
array[i].segno = NULL_SEGNO;
|
array[i].segno = NULL_SEGNO;
|
||||||
array[i].next_blkoff = 0;
|
array[i].next_blkoff = 0;
|
||||||
|
array[i].inited = false;
|
||||||
}
|
}
|
||||||
return restore_curseg_summaries(sbi);
|
return restore_curseg_summaries(sbi);
|
||||||
}
|
}
|
||||||
|
@ -4416,7 +4457,7 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
|
||||||
* In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
|
* In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
|
||||||
* In LFS curseg, all blkaddr after .next_blkoff should be unused.
|
* In LFS curseg, all blkaddr after .next_blkoff should be unused.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < NO_CHECK_TYPE; i++) {
|
for (i = 0; i < NR_PERSISTENT_LOG; i++) {
|
||||||
struct curseg_info *curseg = CURSEG_I(sbi, i);
|
struct curseg_info *curseg = CURSEG_I(sbi, i);
|
||||||
struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
|
struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
|
||||||
unsigned int blkofs = curseg->next_blkoff;
|
unsigned int blkofs = curseg->next_blkoff;
|
||||||
|
@ -4645,7 +4686,7 @@ int f2fs_fix_curseg_write_pointer(struct f2fs_sb_info *sbi)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
for (i = 0; i < NO_CHECK_TYPE; i++) {
|
for (i = 0; i < NR_PERSISTENT_LOG; i++) {
|
||||||
ret = fix_curseg_write_pointer(sbi, i);
|
ret = fix_curseg_write_pointer(sbi, i);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define GET_R2L_SEGNO(free_i, segno) ((segno) + (free_i)->start_segno)
|
#define GET_R2L_SEGNO(free_i, segno) ((segno) + (free_i)->start_segno)
|
||||||
|
|
||||||
#define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
|
#define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
|
||||||
#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
|
#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE && (t) <= CURSEG_COLD_NODE)
|
||||||
|
|
||||||
#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
|
#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
|
||||||
#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
|
#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
|
||||||
|
@ -34,7 +34,8 @@
|
||||||
((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \
|
((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \
|
||||||
((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \
|
((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \
|
||||||
((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \
|
((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \
|
||||||
((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
|
((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno) || \
|
||||||
|
((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno))
|
||||||
|
|
||||||
#define IS_CURSEC(sbi, secno) \
|
#define IS_CURSEC(sbi, secno) \
|
||||||
(((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \
|
(((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \
|
||||||
|
@ -48,7 +49,9 @@
|
||||||
((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \
|
((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \
|
||||||
(sbi)->segs_per_sec) || \
|
(sbi)->segs_per_sec) || \
|
||||||
((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \
|
((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \
|
||||||
(sbi)->segs_per_sec)) \
|
(sbi)->segs_per_sec) || \
|
||||||
|
((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno / \
|
||||||
|
(sbi)->segs_per_sec))
|
||||||
|
|
||||||
#define MAIN_BLKADDR(sbi) \
|
#define MAIN_BLKADDR(sbi) \
|
||||||
(SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \
|
(SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \
|
||||||
|
@ -288,10 +291,12 @@ struct curseg_info {
|
||||||
struct rw_semaphore journal_rwsem; /* protect journal area */
|
struct rw_semaphore journal_rwsem; /* protect journal area */
|
||||||
struct f2fs_journal *journal; /* cached journal info */
|
struct f2fs_journal *journal; /* cached journal info */
|
||||||
unsigned char alloc_type; /* current allocation type */
|
unsigned char alloc_type; /* current allocation type */
|
||||||
|
unsigned short seg_type; /* segment type like CURSEG_XXX_TYPE */
|
||||||
unsigned int segno; /* current segment number */
|
unsigned int segno; /* current segment number */
|
||||||
unsigned short next_blkoff; /* next block offset to write */
|
unsigned short next_blkoff; /* next block offset to write */
|
||||||
unsigned int zone; /* current zone number */
|
unsigned int zone; /* current zone number */
|
||||||
unsigned int next_segno; /* preallocated segment */
|
unsigned int next_segno; /* preallocated segment */
|
||||||
|
bool inited; /* indicate inmem log is inited */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sit_entry_set {
|
struct sit_entry_set {
|
||||||
|
@ -305,8 +310,6 @@ struct sit_entry_set {
|
||||||
*/
|
*/
|
||||||
static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
|
static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
|
||||||
{
|
{
|
||||||
if (type == CURSEG_COLD_DATA_PINNED)
|
|
||||||
type = CURSEG_COLD_DATA;
|
|
||||||
return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
|
return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +442,7 @@ static inline void __set_inuse(struct f2fs_sb_info *sbi,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
|
static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
|
||||||
unsigned int segno)
|
unsigned int segno, bool inmem)
|
||||||
{
|
{
|
||||||
struct free_segmap_info *free_i = FREE_I(sbi);
|
struct free_segmap_info *free_i = FREE_I(sbi);
|
||||||
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
||||||
|
@ -451,7 +454,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
|
||||||
if (test_and_clear_bit(segno, free_i->free_segmap)) {
|
if (test_and_clear_bit(segno, free_i->free_segmap)) {
|
||||||
free_i->free_segments++;
|
free_i->free_segments++;
|
||||||
|
|
||||||
if (IS_CURSEC(sbi, secno))
|
if (!inmem && IS_CURSEC(sbi, secno))
|
||||||
goto skip_free;
|
goto skip_free;
|
||||||
next = find_next_bit(free_i->free_segmap,
|
next = find_next_bit(free_i->free_segmap,
|
||||||
start_segno + sbi->segs_per_sec, start_segno);
|
start_segno + sbi->segs_per_sec, start_segno);
|
||||||
|
|
|
@ -580,7 +580,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
||||||
case Opt_active_logs:
|
case Opt_active_logs:
|
||||||
if (args->from && match_int(args, &arg))
|
if (args->from && match_int(args, &arg))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
|
if (arg != 2 && arg != 4 &&
|
||||||
|
arg != NR_CURSEG_PERSIST_TYPE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
F2FS_OPTION(sbi).active_logs = arg;
|
F2FS_OPTION(sbi).active_logs = arg;
|
||||||
break;
|
break;
|
||||||
|
@ -1001,7 +1002,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not pass down write hints if the number of active logs is lesser
|
/* Not pass down write hints if the number of active logs is lesser
|
||||||
* than NR_CURSEG_TYPE.
|
* than NR_CURSEG_PERSIST_TYPE.
|
||||||
*/
|
*/
|
||||||
if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
|
if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
|
||||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||||
|
@ -1641,7 +1642,7 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
||||||
static void default_options(struct f2fs_sb_info *sbi)
|
static void default_options(struct f2fs_sb_info *sbi)
|
||||||
{
|
{
|
||||||
/* init some FS parameters */
|
/* init some FS parameters */
|
||||||
F2FS_OPTION(sbi).active_logs = NR_CURSEG_TYPE;
|
F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
|
||||||
F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
|
F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
|
||||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||||
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
|
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
|
||||||
|
@ -2996,7 +2997,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
||||||
cp_payload = __cp_payload(sbi);
|
cp_payload = __cp_payload(sbi);
|
||||||
if (cp_pack_start_sum < cp_payload + 1 ||
|
if (cp_pack_start_sum < cp_payload + 1 ||
|
||||||
cp_pack_start_sum > blocks_per_seg - 1 -
|
cp_pack_start_sum > blocks_per_seg - 1 -
|
||||||
NR_CURSEG_TYPE) {
|
NR_CURSEG_PERSIST_TYPE) {
|
||||||
f2fs_err(sbi, "Wrong cp_pack_start_sum: %u",
|
f2fs_err(sbi, "Wrong cp_pack_start_sum: %u",
|
||||||
cp_pack_start_sum);
|
cp_pack_start_sum);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue