summary refs log tree commit diff
path: root/fs/f2fs/gc.h
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2017-08-07 23:12:46 +0800
committerJaegeuk Kim <jaegeuk@kernel.org>2017-08-15 10:40:14 -0700
commitb8c502b81e3f899c6488967dec61eed0f5907db3 (patch)
treeec5f157c9804945eb46dc13b2fc3ab58d9e03bc6 /fs/f2fs/gc.h
parent9a20d391cd099d547c0f17626bf6f13e06da519a (diff)
downloadlinux-b8c502b81e3f899c6488967dec61eed0f5907db3.tar.gz
f2fs: fix potential overflow when adjusting GC cycle
While comparing signed and unsigned variables, compiler will converts the
signed value to unsigned one, due to this reason, {in,de}crease_sleep_time
may return overflowed result.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/gc.h')
-rw-r--r--fs/f2fs/gc.h23
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index 57a9000ce3af..9325191fab2d 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -69,25 +69,32 @@ static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
 }
 
 static inline void increase_sleep_time(struct f2fs_gc_kthread *gc_th,
-								long *wait)
+							unsigned int *wait)
 {
+	unsigned int min_time = gc_th->min_sleep_time;
+	unsigned int max_time = gc_th->max_sleep_time;
+
 	if (*wait == gc_th->no_gc_sleep_time)
 		return;
 
-	*wait += gc_th->min_sleep_time;
-	if (*wait > gc_th->max_sleep_time)
-		*wait = gc_th->max_sleep_time;
+	if ((long long)*wait + (long long)min_time > (long long)max_time)
+		*wait = max_time;
+	else
+		*wait += min_time;
 }
 
 static inline void decrease_sleep_time(struct f2fs_gc_kthread *gc_th,
-								long *wait)
+							unsigned int *wait)
 {
+	unsigned int min_time = gc_th->min_sleep_time;
+
 	if (*wait == gc_th->no_gc_sleep_time)
 		*wait = gc_th->max_sleep_time;
 
-	*wait -= gc_th->min_sleep_time;
-	if (*wait <= gc_th->min_sleep_time)
-		*wait = gc_th->min_sleep_time;
+	if ((long long)*wait - (long long)min_time < (long long)min_time)
+		*wait = min_time;
+	else
+		*wait -= min_time;
 }
 
 static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)