Skip to content

Commit dc6d9ef

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: zone: fix to calculate first_zoned_segno correctly
A zoned device can has both conventional zones and sequential zones, so we should not treat first segment of zoned device as first_zoned_segno, instead, we need to check zone type for each zone during traversing zoned device to find first_zoned_segno. Otherwise, for below case, first_zoned_segno will be 0, which could be wrong. create_null_blk 512 2 1024 1024 mkfs.f2fs -m /dev/nullb0 Testcase: export SCRIPTS_PATH=/share/git/scripts test multiple devices w/ zoned device for ((i=0;i<8;i++)) do { zonesize=$((2<<$i)) conzone=$((4096/$zonesize)) seqzone=$((4096/$zonesize)) $SCRIPTS_PATH/nullblk_create.sh 512 $zonesize $conzone $seqzone mkfs.f2fs -f -m /dev/vdb -c /dev/nullb0 mount /dev/vdb /mnt/f2fs touch /mnt/f2fs/file f2fs_io pinfile set /mnt/f2fs/file $((8589934592*2)) stat /mnt/f2fs/file df cat /proc/fs/f2fs/vdb/segment_info umount /mnt/f2fs $SCRIPTS_PATH/nullblk_remove.sh 0 } done test single zoned device for ((i=0;i<8;i++)) do { zonesize=$((2<<$i)) conzone=$((4096/$zonesize)) seqzone=$((4096/$zonesize)) $SCRIPTS_PATH/nullblk_create.sh 512 $zonesize $conzone $seqzone mkfs.f2fs -f -m /dev/nullb0 mount /dev/nullb0 /mnt/f2fs touch /mnt/f2fs/file f2fs_io pinfile set /mnt/f2fs/file $((8589934592*2)) stat /mnt/f2fs/file df cat /proc/fs/f2fs/nullb0/segment_info umount /mnt/f2fs $SCRIPTS_PATH/nullblk_remove.sh 0 } done Fixes: 9703d69 ("f2fs: support file pinning for zoned devices") Cc: Daeho Jeong <daehojeong@google.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 5db0d25 commit dc6d9ef

4 files changed

Lines changed: 69 additions & 20 deletions

File tree

fs/f2fs/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3967,7 +3967,7 @@ static int check_swap_activate(struct swap_info_struct *sis,
39673967

39683968
if ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec ||
39693969
nr_pblocks % blks_per_sec ||
3970-
!f2fs_valid_pinned_area(sbi, pblock)) {
3970+
f2fs_is_sequential_zone_area(sbi, pblock)) {
39713971
bool last_extent = false;
39723972

39733973
not_aligned++;

fs/f2fs/f2fs.h

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ struct f2fs_sb_info {
17871787
unsigned int dirty_device; /* for checkpoint data flush */
17881788
spinlock_t dev_lock; /* protect dirty_device */
17891789
bool aligned_blksize; /* all devices has the same logical blksize */
1790-
unsigned int first_zoned_segno; /* first zoned segno */
1790+
unsigned int first_seq_zone_segno; /* first segno in sequential zone */
17911791

17921792
/* For write statistics */
17931793
u64 sectors_written_start;
@@ -4620,12 +4620,16 @@ F2FS_FEATURE_FUNCS(readonly, RO);
46204620
F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS);
46214621

46224622
#ifdef CONFIG_BLK_DEV_ZONED
4623-
static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
4624-
block_t blkaddr)
4623+
static inline bool f2fs_zone_is_seq(struct f2fs_sb_info *sbi, int devi,
4624+
unsigned int zone)
46254625
{
4626-
unsigned int zno = blkaddr / sbi->blocks_per_blkz;
4626+
return test_bit(zone, FDEV(devi).blkz_seq);
4627+
}
46274628

4628-
return test_bit(zno, FDEV(devi).blkz_seq);
4629+
static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
4630+
block_t blkaddr)
4631+
{
4632+
return f2fs_zone_is_seq(sbi, devi, blkaddr / sbi->blocks_per_blkz);
46294633
}
46304634
#endif
46314635

@@ -4697,15 +4701,31 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi)
46974701
return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
46984702
}
46994703

4700-
static inline bool f2fs_valid_pinned_area(struct f2fs_sb_info *sbi,
4704+
static inline bool f2fs_is_sequential_zone_area(struct f2fs_sb_info *sbi,
47014705
block_t blkaddr)
47024706
{
47034707
if (f2fs_sb_has_blkzoned(sbi)) {
4708+
#ifdef CONFIG_BLK_DEV_ZONED
47044709
int devi = f2fs_target_device_index(sbi, blkaddr);
47054710

4706-
return !bdev_is_zoned(FDEV(devi).bdev);
4711+
if (!bdev_is_zoned(FDEV(devi).bdev))
4712+
return false;
4713+
4714+
if (f2fs_is_multi_device(sbi)) {
4715+
if (blkaddr < FDEV(devi).start_blk ||
4716+
blkaddr > FDEV(devi).end_blk) {
4717+
f2fs_err(sbi, "Invalid block %x", blkaddr);
4718+
return false;
4719+
}
4720+
blkaddr -= FDEV(devi).start_blk;
4721+
}
4722+
4723+
return f2fs_blkz_is_seq(sbi, devi, blkaddr);
4724+
#else
4725+
return false;
4726+
#endif
47074727
}
4708-
return true;
4728+
return false;
47094729
}
47104730

47114731
static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi)

fs/f2fs/segment.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,7 +2783,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
27832783
if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning)
27842784
segno = 0;
27852785
else
2786-
segno = max(sbi->first_zoned_segno, *newseg);
2786+
segno = max(sbi->first_seq_zone_segno, *newseg);
27872787
hint = GET_SEC_FROM_SEG(sbi, segno);
27882788
}
27892789
#endif
@@ -2795,7 +2795,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
27952795
if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
27962796
/* Write only to sequential zones */
27972797
if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
2798-
hint = GET_SEC_FROM_SEG(sbi, sbi->first_zoned_segno);
2798+
hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
27992799
secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
28002800
} else
28012801
secno = find_first_zero_bit(free_i->free_secmap,
@@ -2844,9 +2844,9 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
28442844
/* set it as dirty segment in free segmap */
28452845
f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
28462846

2847-
/* no free section in conventional zone */
2847+
/* no free section in conventional device or conventional zone */
28482848
if (new_sec && pinning &&
2849-
!f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
2849+
f2fs_is_sequential_zone_area(sbi, START_BLOCK(sbi, segno))) {
28502850
ret = -EAGAIN;
28512851
goto out_unlock;
28522852
}
@@ -3317,7 +3317,7 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
33173317

33183318
if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) {
33193319
f2fs_down_write(&sbi->gc_lock);
3320-
err = f2fs_gc_range(sbi, 0, GET_SEGNO(sbi, FDEV(0).end_blk),
3320+
err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1,
33213321
true, ZONED_PIN_SEC_REQUIRED_COUNT);
33223322
f2fs_up_write(&sbi->gc_lock);
33233323

fs/f2fs/super.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4311,14 +4311,35 @@ static void f2fs_record_error_work(struct work_struct *work)
43114311
f2fs_record_stop_reason(sbi);
43124312
}
43134313

4314-
static inline unsigned int get_first_zoned_segno(struct f2fs_sb_info *sbi)
4314+
static inline unsigned int get_first_seq_zone_segno(struct f2fs_sb_info *sbi)
43154315
{
4316+
#ifdef CONFIG_BLK_DEV_ZONED
4317+
unsigned int zoneno, total_zones;
43164318
int devi;
43174319

4318-
for (devi = 0; devi < sbi->s_ndevs; devi++)
4319-
if (bdev_is_zoned(FDEV(devi).bdev))
4320-
return GET_SEGNO(sbi, FDEV(devi).start_blk);
4321-
return 0;
4320+
if (!f2fs_sb_has_blkzoned(sbi))
4321+
return NULL_SEGNO;
4322+
4323+
for (devi = 0; devi < sbi->s_ndevs; devi++) {
4324+
if (!bdev_is_zoned(FDEV(devi).bdev))
4325+
continue;
4326+
4327+
total_zones = GET_ZONE_FROM_SEG(sbi, FDEV(devi).total_segments);
4328+
4329+
for (zoneno = 0; zoneno < total_zones; zoneno++) {
4330+
unsigned int segs, blks;
4331+
4332+
if (!f2fs_zone_is_seq(sbi, devi, zoneno))
4333+
continue;
4334+
4335+
segs = GET_SEG_FROM_SEC(sbi,
4336+
zoneno * sbi->secs_per_zone);
4337+
blks = SEGS_TO_BLKS(sbi, segs);
4338+
return GET_SEGNO(sbi, FDEV(devi).start_blk + blks);
4339+
}
4340+
}
4341+
#endif
4342+
return NULL_SEGNO;
43224343
}
43234344

43244345
static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
@@ -4355,6 +4376,14 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
43554376
#endif
43564377

43574378
for (i = 0; i < max_devices; i++) {
4379+
if (max_devices == 1) {
4380+
FDEV(i).total_segments =
4381+
le32_to_cpu(raw_super->segment_count_main);
4382+
FDEV(i).start_blk = 0;
4383+
FDEV(i).end_blk = FDEV(i).total_segments *
4384+
BLKS_PER_SEG(sbi);
4385+
}
4386+
43584387
if (i == 0)
43594388
FDEV(0).bdev_file = sbi->sb->s_bdev_file;
43604389
else if (!RDEV(i).path[0])
@@ -4725,7 +4754,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
47254754
sbi->sectors_written_start = f2fs_get_sectors_written(sbi);
47264755

47274756
/* get segno of first zoned block device */
4728-
sbi->first_zoned_segno = get_first_zoned_segno(sbi);
4757+
sbi->first_seq_zone_segno = get_first_seq_zone_segno(sbi);
47294758

47304759
/* Read accumulated write IO statistics if exists */
47314760
seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);

0 commit comments

Comments
 (0)