mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	f2fs: introduce sbi->gc_mode to determine the policy
This is to avoid sbi->gc_thread pointer access. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
		
							parent
							
								
									107a805de8
								
							
						
					
					
						commit
						5b0e95398e
					
				
					 5 changed files with 47 additions and 28 deletions
				
			
		| 
						 | 
					@ -1066,6 +1066,13 @@ enum {
 | 
				
			||||||
	MAX_TIME,
 | 
						MAX_TIME,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						GC_NORMAL,
 | 
				
			||||||
 | 
						GC_IDLE_CB,
 | 
				
			||||||
 | 
						GC_IDLE_GREEDY,
 | 
				
			||||||
 | 
						GC_URGENT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	WHINT_MODE_OFF,		/* not pass down write hints */
 | 
						WHINT_MODE_OFF,		/* not pass down write hints */
 | 
				
			||||||
	WHINT_MODE_USER,	/* try to pass down hints given by users */
 | 
						WHINT_MODE_USER,	/* try to pass down hints given by users */
 | 
				
			||||||
| 
						 | 
					@ -1197,6 +1204,7 @@ struct f2fs_sb_info {
 | 
				
			||||||
	struct mutex gc_mutex;			/* mutex for GC */
 | 
						struct mutex gc_mutex;			/* mutex for GC */
 | 
				
			||||||
	struct f2fs_gc_kthread	*gc_thread;	/* GC thread */
 | 
						struct f2fs_gc_kthread	*gc_thread;	/* GC thread */
 | 
				
			||||||
	unsigned int cur_victim_sec;		/* current victim section num */
 | 
						unsigned int cur_victim_sec;		/* current victim section num */
 | 
				
			||||||
 | 
						unsigned int gc_mode;			/* current GC state */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* threshold for gc trials on pinned files */
 | 
						/* threshold for gc trials on pinned files */
 | 
				
			||||||
	u64 gc_pin_file_threshold;
 | 
						u64 gc_pin_file_threshold;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								fs/f2fs/gc.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								fs/f2fs/gc.c
									
									
									
									
									
								
							| 
						 | 
					@ -76,7 +76,7 @@ static int gc_thread_func(void *data)
 | 
				
			||||||
		 * invalidated soon after by user update or deletion.
 | 
							 * invalidated soon after by user update or deletion.
 | 
				
			||||||
		 * So, I'd like to wait some time to collect dirty segments.
 | 
							 * So, I'd like to wait some time to collect dirty segments.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (gc_th->gc_urgent) {
 | 
							if (sbi->gc_mode == GC_URGENT) {
 | 
				
			||||||
			wait_ms = gc_th->urgent_sleep_time;
 | 
								wait_ms = gc_th->urgent_sleep_time;
 | 
				
			||||||
			mutex_lock(&sbi->gc_mutex);
 | 
								mutex_lock(&sbi->gc_mutex);
 | 
				
			||||||
			goto do_gc;
 | 
								goto do_gc;
 | 
				
			||||||
| 
						 | 
					@ -131,8 +131,6 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
 | 
				
			||||||
	gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
 | 
						gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
 | 
				
			||||||
	gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
 | 
						gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gc_th->gc_idle = 0;
 | 
					 | 
				
			||||||
	gc_th->gc_urgent = 0;
 | 
					 | 
				
			||||||
	gc_th->gc_wake= 0;
 | 
						gc_th->gc_wake= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sbi->gc_thread = gc_th;
 | 
						sbi->gc_thread = gc_th;
 | 
				
			||||||
| 
						 | 
					@ -158,21 +156,19 @@ void stop_gc_thread(struct f2fs_sb_info *sbi)
 | 
				
			||||||
	sbi->gc_thread = NULL;
 | 
						sbi->gc_thread = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type)
 | 
					static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
 | 
						int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!gc_th)
 | 
						switch (sbi->gc_mode) {
 | 
				
			||||||
		return gc_mode;
 | 
						case GC_IDLE_CB:
 | 
				
			||||||
 | 
							gc_mode = GC_CB;
 | 
				
			||||||
	if (gc_th->gc_idle) {
 | 
							break;
 | 
				
			||||||
		if (gc_th->gc_idle == 1)
 | 
						case GC_IDLE_GREEDY:
 | 
				
			||||||
			gc_mode = GC_CB;
 | 
						case GC_URGENT:
 | 
				
			||||||
		else if (gc_th->gc_idle == 2)
 | 
					 | 
				
			||||||
			gc_mode = GC_GREEDY;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (gc_th->gc_urgent)
 | 
					 | 
				
			||||||
		gc_mode = GC_GREEDY;
 | 
							gc_mode = GC_GREEDY;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return gc_mode;
 | 
						return gc_mode;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -187,7 +183,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
 | 
				
			||||||
		p->max_search = dirty_i->nr_dirty[type];
 | 
							p->max_search = dirty_i->nr_dirty[type];
 | 
				
			||||||
		p->ofs_unit = 1;
 | 
							p->ofs_unit = 1;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		p->gc_mode = select_gc_type(sbi->gc_thread, gc_type);
 | 
							p->gc_mode = select_gc_type(sbi, gc_type);
 | 
				
			||||||
		p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
 | 
							p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
 | 
				
			||||||
		p->max_search = dirty_i->nr_dirty[DIRTY];
 | 
							p->max_search = dirty_i->nr_dirty[DIRTY];
 | 
				
			||||||
		p->ofs_unit = sbi->segs_per_sec;
 | 
							p->ofs_unit = sbi->segs_per_sec;
 | 
				
			||||||
| 
						 | 
					@ -195,7 +191,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* we need to check every dirty segments in the FG_GC case */
 | 
						/* we need to check every dirty segments in the FG_GC case */
 | 
				
			||||||
	if (gc_type != FG_GC &&
 | 
						if (gc_type != FG_GC &&
 | 
				
			||||||
			(sbi->gc_thread && !sbi->gc_thread->gc_urgent) &&
 | 
								(sbi->gc_mode != GC_URGENT) &&
 | 
				
			||||||
			p->max_search > sbi->max_victim_search)
 | 
								p->max_search > sbi->max_victim_search)
 | 
				
			||||||
		p->max_search = sbi->max_victim_search;
 | 
							p->max_search = sbi->max_victim_search;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,8 +36,6 @@ struct f2fs_gc_kthread {
 | 
				
			||||||
	unsigned int no_gc_sleep_time;
 | 
						unsigned int no_gc_sleep_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* for changing gc mode */
 | 
						/* for changing gc mode */
 | 
				
			||||||
	unsigned int gc_idle;
 | 
					 | 
				
			||||||
	unsigned int gc_urgent;
 | 
					 | 
				
			||||||
	unsigned int gc_wake;
 | 
						unsigned int gc_wake;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@ bool need_SSR(struct f2fs_sb_info *sbi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (test_opt(sbi, LFS))
 | 
						if (test_opt(sbi, LFS))
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
 | 
						if (sbi->gc_mode == GC_URGENT)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
 | 
						return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
 | 
				
			||||||
| 
						 | 
					@ -1405,7 +1405,7 @@ static int issue_discard_thread(void *data)
 | 
				
			||||||
		if (dcc->discard_wake)
 | 
							if (dcc->discard_wake)
 | 
				
			||||||
			dcc->discard_wake = 0;
 | 
								dcc->discard_wake = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
 | 
							if (sbi->gc_mode == GC_URGENT)
 | 
				
			||||||
			__init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
 | 
								__init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sb_start_intwrite(sbi->sb);
 | 
							sb_start_intwrite(sbi->sb);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -248,16 +248,33 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
 | 
				
			||||||
	if (!strcmp(a->attr.name, "trim_sections"))
 | 
						if (!strcmp(a->attr.name, "trim_sections"))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(a->attr.name, "gc_urgent")) {
 | 
				
			||||||
 | 
							if (t >= 1) {
 | 
				
			||||||
 | 
								sbi->gc_mode = GC_URGENT;
 | 
				
			||||||
 | 
								if (sbi->gc_thread) {
 | 
				
			||||||
 | 
									wake_up_interruptible_all(
 | 
				
			||||||
 | 
										&sbi->gc_thread->gc_wait_queue_head);
 | 
				
			||||||
 | 
									wake_up_discard_thread(sbi, true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sbi->gc_mode = GC_NORMAL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return count;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!strcmp(a->attr.name, "gc_idle")) {
 | 
				
			||||||
 | 
							if (t == GC_IDLE_CB)
 | 
				
			||||||
 | 
								sbi->gc_mode = GC_IDLE_CB;
 | 
				
			||||||
 | 
							else if (t == GC_IDLE_GREEDY)
 | 
				
			||||||
 | 
								sbi->gc_mode = GC_IDLE_GREEDY;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								sbi->gc_mode = GC_NORMAL;
 | 
				
			||||||
 | 
							return count;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*ui = t;
 | 
						*ui = t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
 | 
						if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
 | 
				
			||||||
		f2fs_reset_iostat(sbi);
 | 
							f2fs_reset_iostat(sbi);
 | 
				
			||||||
	if (!strcmp(a->attr.name, "gc_urgent") && t == 1 && sbi->gc_thread) {
 | 
					 | 
				
			||||||
		sbi->gc_thread->gc_wake = 1;
 | 
					 | 
				
			||||||
		wake_up_interruptible_all(&sbi->gc_thread->gc_wait_queue_head);
 | 
					 | 
				
			||||||
		wake_up_discard_thread(sbi, true);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,8 +366,8 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
 | 
				
			||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
 | 
					F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
 | 
				
			||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
 | 
					F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
 | 
				
			||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
 | 
					F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
 | 
				
			||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
 | 
					F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
 | 
				
			||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent, gc_urgent);
 | 
					F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
 | 
				
			||||||
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
 | 
					F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
 | 
				
			||||||
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
 | 
					F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
 | 
				
			||||||
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
 | 
					F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue