f2fs: enforce single zone capacity
[ Upstream commit b771aadc6e4c221a468fe4a2dfcfffec01a06722 ] In order to simplify the complicated per-zone capacity, let's support only one capacity for entire zoned device. Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Stable-dep-of: 0b37ed21e336 ("f2fs: apply zone capacity to all zone type") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c3a1914b96
commit
d420c4a06d
@@ -1153,7 +1153,6 @@ struct f2fs_dev_info {
|
|||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
unsigned int nr_blkz; /* Total number of zones */
|
unsigned int nr_blkz; /* Total number of zones */
|
||||||
unsigned long *blkz_seq; /* Bitmap indicating sequential zones */
|
unsigned long *blkz_seq; /* Bitmap indicating sequential zones */
|
||||||
block_t *zone_capacity_blocks; /* Array of zone capacity in blks */
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1422,6 +1421,7 @@ struct f2fs_sb_info {
|
|||||||
unsigned int meta_ino_num; /* meta inode number*/
|
unsigned int meta_ino_num; /* meta inode number*/
|
||||||
unsigned int log_blocks_per_seg; /* log2 blocks per segment */
|
unsigned int log_blocks_per_seg; /* log2 blocks per segment */
|
||||||
unsigned int blocks_per_seg; /* blocks per segment */
|
unsigned int blocks_per_seg; /* blocks per segment */
|
||||||
|
unsigned int unusable_blocks_per_sec; /* unusable blocks per section */
|
||||||
unsigned int segs_per_sec; /* segments per section */
|
unsigned int segs_per_sec; /* segments per section */
|
||||||
unsigned int secs_per_zone; /* sections per zone */
|
unsigned int secs_per_zone; /* sections per zone */
|
||||||
unsigned int total_sections; /* total section count */
|
unsigned int total_sections; /* total section count */
|
||||||
|
|||||||
@@ -4982,7 +4982,7 @@ static unsigned int get_zone_idx(struct f2fs_sb_info *sbi, unsigned int secno,
|
|||||||
static inline unsigned int f2fs_usable_zone_segs_in_sec(
|
static inline unsigned int f2fs_usable_zone_segs_in_sec(
|
||||||
struct f2fs_sb_info *sbi, unsigned int segno)
|
struct f2fs_sb_info *sbi, unsigned int segno)
|
||||||
{
|
{
|
||||||
unsigned int dev_idx, zone_idx, unusable_segs_in_sec;
|
unsigned int dev_idx, zone_idx;
|
||||||
|
|
||||||
dev_idx = f2fs_target_device_index(sbi, START_BLOCK(sbi, segno));
|
dev_idx = f2fs_target_device_index(sbi, START_BLOCK(sbi, segno));
|
||||||
zone_idx = get_zone_idx(sbi, GET_SEC_FROM_SEG(sbi, segno), dev_idx);
|
zone_idx = get_zone_idx(sbi, GET_SEC_FROM_SEG(sbi, segno), dev_idx);
|
||||||
@@ -4991,18 +4991,12 @@ static inline unsigned int f2fs_usable_zone_segs_in_sec(
|
|||||||
if (is_conv_zone(sbi, zone_idx, dev_idx))
|
if (is_conv_zone(sbi, zone_idx, dev_idx))
|
||||||
return sbi->segs_per_sec;
|
return sbi->segs_per_sec;
|
||||||
|
|
||||||
/*
|
if (!sbi->unusable_blocks_per_sec)
|
||||||
* If the zone_capacity_blocks array is NULL, then zone capacity
|
|
||||||
* is equal to the zone size for all zones
|
|
||||||
*/
|
|
||||||
if (!FDEV(dev_idx).zone_capacity_blocks)
|
|
||||||
return sbi->segs_per_sec;
|
return sbi->segs_per_sec;
|
||||||
|
|
||||||
/* Get the segment count beyond zone capacity block */
|
/* Get the segment count beyond zone capacity block */
|
||||||
unusable_segs_in_sec = (sbi->blocks_per_blkz -
|
return sbi->segs_per_sec - (sbi->unusable_blocks_per_sec >>
|
||||||
FDEV(dev_idx).zone_capacity_blocks[zone_idx]) >>
|
sbi->log_blocks_per_seg);
|
||||||
sbi->log_blocks_per_seg;
|
|
||||||
return sbi->segs_per_sec - unusable_segs_in_sec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -5031,12 +5025,11 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg(
|
|||||||
if (is_conv_zone(sbi, zone_idx, dev_idx))
|
if (is_conv_zone(sbi, zone_idx, dev_idx))
|
||||||
return sbi->blocks_per_seg;
|
return sbi->blocks_per_seg;
|
||||||
|
|
||||||
if (!FDEV(dev_idx).zone_capacity_blocks)
|
if (!sbi->unusable_blocks_per_sec)
|
||||||
return sbi->blocks_per_seg;
|
return sbi->blocks_per_seg;
|
||||||
|
|
||||||
sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno));
|
sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno));
|
||||||
sec_cap_blkaddr = sec_start_blkaddr +
|
sec_cap_blkaddr = sec_start_blkaddr + CAP_BLKS_PER_SEC(sbi);
|
||||||
FDEV(dev_idx).zone_capacity_blocks[zone_idx];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If segment starts before zone capacity and spans beyond
|
* If segment starts before zone capacity and spans beyond
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
|
|||||||
GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
|
GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
|
||||||
#define BLKS_PER_SEC(sbi) \
|
#define BLKS_PER_SEC(sbi) \
|
||||||
((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
|
((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
|
||||||
|
#define CAP_BLKS_PER_SEC(sbi) \
|
||||||
|
((sbi)->segs_per_sec * (sbi)->blocks_per_seg - \
|
||||||
|
(sbi)->unusable_blocks_per_sec)
|
||||||
#define GET_SEC_FROM_SEG(sbi, segno) \
|
#define GET_SEC_FROM_SEG(sbi, segno) \
|
||||||
(((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec)
|
(((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec)
|
||||||
#define GET_SEG_FROM_SEC(sbi, secno) \
|
#define GET_SEG_FROM_SEC(sbi, secno) \
|
||||||
|
|||||||
@@ -1242,7 +1242,6 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
|
|||||||
blkdev_put(FDEV(i).bdev, FMODE_EXCL);
|
blkdev_put(FDEV(i).bdev, FMODE_EXCL);
|
||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
kvfree(FDEV(i).blkz_seq);
|
kvfree(FDEV(i).blkz_seq);
|
||||||
kfree(FDEV(i).zone_capacity_blocks);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
kvfree(sbi->devs);
|
kvfree(sbi->devs);
|
||||||
@@ -3199,24 +3198,29 @@ static int init_percpu_info(struct f2fs_sb_info *sbi)
|
|||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
|
|
||||||
struct f2fs_report_zones_args {
|
struct f2fs_report_zones_args {
|
||||||
|
struct f2fs_sb_info *sbi;
|
||||||
struct f2fs_dev_info *dev;
|
struct f2fs_dev_info *dev;
|
||||||
bool zone_cap_mismatch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx,
|
static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct f2fs_report_zones_args *rz_args = data;
|
struct f2fs_report_zones_args *rz_args = data;
|
||||||
|
block_t unusable_blocks = (zone->len - zone->capacity) >>
|
||||||
|
F2FS_LOG_SECTORS_PER_BLOCK;
|
||||||
|
|
||||||
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
|
if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
set_bit(idx, rz_args->dev->blkz_seq);
|
set_bit(idx, rz_args->dev->blkz_seq);
|
||||||
rz_args->dev->zone_capacity_blocks[idx] = zone->capacity >>
|
if (!rz_args->sbi->unusable_blocks_per_sec) {
|
||||||
F2FS_LOG_SECTORS_PER_BLOCK;
|
rz_args->sbi->unusable_blocks_per_sec = unusable_blocks;
|
||||||
if (zone->len != zone->capacity && !rz_args->zone_cap_mismatch)
|
return 0;
|
||||||
rz_args->zone_cap_mismatch = true;
|
}
|
||||||
|
if (rz_args->sbi->unusable_blocks_per_sec != unusable_blocks) {
|
||||||
|
f2fs_err(rz_args->sbi, "F2FS supports single zone capacity\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3250,26 +3254,13 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
|
|||||||
if (!FDEV(devi).blkz_seq)
|
if (!FDEV(devi).blkz_seq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Get block zones type and zone-capacity */
|
rep_zone_arg.sbi = sbi;
|
||||||
FDEV(devi).zone_capacity_blocks = f2fs_kzalloc(sbi,
|
|
||||||
FDEV(devi).nr_blkz * sizeof(block_t),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!FDEV(devi).zone_capacity_blocks)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rep_zone_arg.dev = &FDEV(devi);
|
rep_zone_arg.dev = &FDEV(devi);
|
||||||
rep_zone_arg.zone_cap_mismatch = false;
|
|
||||||
|
|
||||||
ret = blkdev_report_zones(bdev, 0, BLK_ALL_ZONES, f2fs_report_zone_cb,
|
ret = blkdev_report_zones(bdev, 0, BLK_ALL_ZONES, f2fs_report_zone_cb,
|
||||||
&rep_zone_arg);
|
&rep_zone_arg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!rep_zone_arg.zone_cap_mismatch) {
|
|
||||||
kfree(FDEV(devi).zone_capacity_blocks);
|
|
||||||
FDEV(devi).zone_capacity_blocks = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user