Commit 178053e2 authored by Damien Le Moal's avatar Damien Le Moal Committed by Jaegeuk Kim

f2fs: Cache zoned block devices zone type

With the zoned block device feature enabled, section discard
need to do a zone reset for sections contained in sequential
zones, and a regular discard (if supported) for sections
stored in conventional zones. Avoid the need for a costly
report zones to obtain a section zone type when discarding it
by caching the types of the device zones in the super block
information. This cache is initialized at mount time for mounts
with the zoned block device feature enabled.
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 3adc57e9
......@@ -756,6 +756,14 @@ struct f2fs_sb_info {
u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE];
u8 key_prefix_size;
#endif
#ifdef CONFIG_BLK_DEV_ZONED
unsigned int nr_blkz; /* Total number of zones */
unsigned int blocks_per_blkz; /* F2FS blocks per zone */
unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */
u8 *blkz_type; /* Array of zones type */
#endif
/* for node-related operations */
struct f2fs_nm_info *nm_info; /* node manager */
struct inode *node_inode; /* cache node blocks */
......@@ -2416,6 +2424,16 @@ static inline int f2fs_sb_mounted_blkzoned(struct super_block *sb)
return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_BLKZONED);
}
#ifdef CONFIG_BLK_DEV_ZONED
static inline int get_blkz_type(struct f2fs_sb_info *sbi,
block_t blkaddr)
{
unsigned int zno = blkaddr >> sbi->log_blocks_per_blkz;
return sbi->blkz_type[zno];
}
#endif
static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi)
{
struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
......
......@@ -1511,6 +1511,65 @@ static int init_percpu_info(struct f2fs_sb_info *sbi)
GFP_KERNEL);
}
#ifdef CONFIG_BLK_DEV_ZONED
static int init_blkz_info(struct f2fs_sb_info *sbi)
{
struct block_device *bdev = sbi->sb->s_bdev;
sector_t nr_sectors = bdev->bd_part->nr_sects;
sector_t sector = 0;
struct blk_zone *zones;
unsigned int i, nr_zones;
unsigned int n = 0;
int err = -EIO;
if (!f2fs_sb_mounted_blkzoned(sbi->sb))
return 0;
sbi->blocks_per_blkz = SECTOR_TO_BLOCK(bdev_zone_size(bdev));
sbi->log_blocks_per_blkz = __ilog2_u32(sbi->blocks_per_blkz);
sbi->nr_blkz = SECTOR_TO_BLOCK(nr_sectors) >>
sbi->log_blocks_per_blkz;
if (nr_sectors & (bdev_zone_size(bdev) - 1))
sbi->nr_blkz++;
sbi->blkz_type = kmalloc(sbi->nr_blkz, GFP_KERNEL);
if (!sbi->blkz_type)
return -ENOMEM;
#define F2FS_REPORT_NR_ZONES 4096
zones = kcalloc(F2FS_REPORT_NR_ZONES, sizeof(struct blk_zone),
GFP_KERNEL);
if (!zones)
return -ENOMEM;
/* Get block zones type */
while (zones && sector < nr_sectors) {
nr_zones = F2FS_REPORT_NR_ZONES;
err = blkdev_report_zones(bdev, sector,
zones, &nr_zones,
GFP_KERNEL);
if (err)
break;
if (!nr_zones) {
err = -EIO;
break;
}
for (i = 0; i < nr_zones; i++) {
sbi->blkz_type[n] = zones[i].type;
sector += zones[i].len;
n++;
}
}
kfree(zones);
return err;
}
#endif
/*
* Read f2fs raw super block.
* Because we have two copies of super block, so read both of them
......@@ -1757,6 +1816,15 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
init_ino_entry_info(sbi);
#ifdef CONFIG_BLK_DEV_ZONED
err = init_blkz_info(sbi);
if (err) {
f2fs_msg(sb, KERN_ERR,
"Failed to initialize F2FS blkzone information");
goto free_blkz;
}
#endif
/* setup f2fs internal modules */
err = build_segment_manager(sbi);
if (err) {
......@@ -1935,6 +2003,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
destroy_node_manager(sbi);
free_sm:
destroy_segment_manager(sbi);
#ifdef CONFIG_BLK_DEV_ZONED
free_blkz:
kfree(sbi->blkz_type);
#endif
kfree(sbi->ckpt);
free_meta_inode:
make_bad_inode(sbi->meta_inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment