Skip to content

Commit

Permalink
f2fs: Fix type of section block count variables
Browse files Browse the repository at this point in the history
Commit da52f8a ("f2fs: get the right gc victim section when section
has several segments") added code to count blocks of each section using
variables with type 'unsigned short', which has 2 bytes size in many
systems. However, the counts can be larger than the 2 bytes range and
type conversion results in wrong values. Especially when the f2fs
sections have blocks as many as USHRT_MAX + 1, the count is handled as 0.
This triggers eternal loop in init_dirty_segmap() at mount system call.
Fix this by changing the type of the variables to block_t.

Fixes: da52f8a ("f2fs: get the right gc victim section when section has several segments")
Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
Reviewed-by: Chao Yu <[email protected]>
Signed-off-by: Jaegeuk Kim <[email protected]>
  • Loading branch information
kawasaki authored and Jaegeuk Kim committed Sep 9, 2020
1 parent 34d4ddd commit 123aaf7
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions fs/f2fs/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,

if (__is_large_section(sbi)) {
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
unsigned short valid_blocks =
block_t valid_blocks =
get_valid_blocks(sbi, segno, true);

f2fs_bug_on(sbi, unlikely(!valid_blocks ||
Expand All @@ -815,7 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
enum dirty_type dirty_type)
{
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
unsigned short valid_blocks;
block_t valid_blocks;

if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
dirty_i->nr_dirty[dirty_type]--;
Expand Down Expand Up @@ -4316,8 +4316,8 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
struct free_segmap_info *free_i = FREE_I(sbi);
unsigned int segno = 0, offset = 0, secno;
unsigned short valid_blocks;
unsigned short blks_per_sec = BLKS_PER_SEC(sbi);
block_t valid_blocks;
block_t blks_per_sec = BLKS_PER_SEC(sbi);

while (1) {
/* find dirty segment based on free segmap */
Expand Down

0 comments on commit 123aaf7

Please sign in to comment.