f2fs系列文章gc

    这篇文章将讲述f2fs的gc,其主要的步骤应该是分为两步,首先select一个合适的section,然后将section中的数据全部迁移。

 

    f2fs_gc:这个函数主要有两个函数调用gc线程和f2fs_balance_fs。首先检查super_block是否设置MS_ACTIVE,也就是super_block处于活动状态(目前不知道什么个状态),如果设置了就不做gc了。然后再检查是否设置了CP_ERROR_FLAG(这个表示文件系统的没有稳定的cp pack),如果设置了,也是不做gc了。如果此时是BG_GC并且已经没有足够的section了,那么将gc_type设置成FG_GC。如果这种情况下,没有废弃的prefree segment并且调用get_victim函数也没有获得section,但是还有足够的section,那么此时不需做write_checkpoint,其他情况下都要进行write_checkpoint并且选择的segno被设置成NULL_SEGNO。接着检查调用get_victim_by_default来选择victim section来进行垃圾回收。然后就调用do_garbage_collect对选择的section进行数据的迁移。如果是BG_GC进入的f2fs_gc,这个时候还需要检查有没有足够的section,如果没有的话,继续回去进行新一轮的回收,另外如果此时的gc_type是FG_GC,那么进行write_checkpoint操作。

int f2fs_gc(struct f2fs_sb_info *sbi, bool sync)
{
	unsigned int segno;
	int gc_type = sync ? FG_GC : BG_GC;
	int sec_freed = 0;
	int ret = -EINVAL;
	struct cp_control cpc;
	struct gc_inode_list gc_list = {
		.ilist = LIST_HEAD_INIT(gc_list.ilist),
		.iroot = RADIX_TREE_INIT(GFP_NOFS),
	};

	cpc.reason = __get_cp_reason(sbi);
gc_more:
	segno = NULL_SEGNO;

	if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE)))
		goto stop;
	if (unlikely(f2fs_cp_error(sbi))) {
		ret = -EIO;
		goto stop;
	}

	if (gc_type == BG_GC && has_not_enough_free_secs(sbi, sec_freed, 0)) {
		gc_type = FG_GC;
		if (__get_victim(sbi, &segno, gc_type) || prefree_segments(sbi)) {
			ret = write_checkpoint(sbi, &cpc);
			if (ret)
				goto stop;
			segno = NULL_SEGNO;
		} else if (has_not_enough_free_secs(sbi, 0, 0)) {
			ret = write_checkpoint(sbi, &cpc);
			if (ret)
				goto stop;
		}
	}

	if (segno == NULL_SEGNO && !__get_victim(sbi, &segno, gc_type))
		goto stop;
	ret = 0;

	if (do_garbage_collect(sbi, segno, &gc_list, gc_type) &&
			gc_type == FG_GC)
		sec_freed++;

	if (gc_type == FG_GC)
		sbi->cur_victim_sec = NULL_SEGNO;

	if (!sync) {
		if (has_not_enough_free_secs(sbi, sec_freed, 0))
			goto gc_more;

		if (gc_type == FG_GC)
			ret = write_checkpoint(sbi, &cpc);
	}
stop:
	mutex_unlock(&sbi->gc_mutex);

	put_gc_inode(&gc_list);

	if (sync)
		ret = sec_freed ? 0 : -EAGAIN;
	return ret;
}

    get_victim_by_default:首先初始化选择过程中使用到的数据结构victim_sel_policy,先说一下其字段的含义:alloc_mode,可以取值LFS和SSR,选择过程中这两种的处理模式是不同的。gc_mode这个是计算cost的算法,取值GC_CB和GC_GREEDY。dirty_segmap是记录dirty的segment的位图,选择过程中需要在dirty的segment的section中选择。max_search表示查找过程中的最多的segment的数量,实际就是上述位图的dirty的segment的数量。offset表示在便利过程中的当前的查找偏移。ofs_unit表示在查找过程中每次查找跨越的单元,SSR是以1个segment为单元,LFS是以1个section为单元。min_cost记录查找过程中的最小cost。min_segno记录的是查找过程中最小cost所对应的segno。

struct victim_sel_policy {
	int alloc_mode;	
	int gc_mode;
	unsigned long *dirty_segmap;
	unsigned int max_search;
	unsigned int offset;
	unsigned int ofs_unit;
	unsigned int min_cost;
	unsigned int min_segno;
};

    所以其初始化时通过函数select_policy完成的。然后检查是不是以LSF并且是FG_GC的方式进行select,如果是就直接使用之前BG_GC选择过的GC(这样选择的section其有效块数比较少,具体原因不清楚)。如果对应的segno不是NULL_SEGNO,那就找到了。否则需要跟其他的一样对所有的有脏的segment的section进行计算cost,然后选择出最小的cost作为最后的结果。可能是为了均匀的原因,这个遍历不是从头开始的,而是从上次的选择开始的,然后遍历整个循环。首先通过函数find_next

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值