diff options
author | Aravind Ramesh <aravind.ramesh@wdc.com> | 2020-07-21 22:08:11 +0530 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2020-08-20 09:08:34 -0700 |
commit | f8410857b7a81b1b347253fcca713d8b105e9e7b (patch) | |
tree | aeb1c1ab70c8d7c9b872d9bfe2846ca440e4d14b /include/f2fs_fs.h | |
parent | 1e3dd7ae5de14b641c6717cb462fd139351d41f3 (diff) | |
download | f2fs-tools-f8410857b7a81b1b347253fcca713d8b105e9e7b.tar.gz |
f2fs-tools: zns zone-capacity support
NVM Express Zoned Namespace (ZNS) devices can have zone-capacity(zc) less
than the zone-size. ZNS defines a per zone capacity which can be equal
or less than the zone-size. Zone-capacity is the number of usable blocks
in the zone. If zone-capacity is less than zone-size, then the segments
which start at/after zone-capacity are considered unusable. Only those
segments which start before the zone-capacity are considered as usable
and added to the free_segment_count and free_segment_bitmap of the kernel.
In such cases, the filesystem should not write/read beyond the
zone-capacity.
Update the super block with the usable number of blocks and free segment
count in the ZNS device zones, if zone-capacity is less than zone-size.
Set reserved segment count and overprovision ratio based on the usable
segments in the zone.
Allow fsck to find the free_segment_count based on the zone-capacity and
compare with checkpoint values.
Signed-off-by: Aravind Ramesh <aravind.ramesh@wdc.com>
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
[Jaegeuk Kim: add UNUSED to is_usable_seg()]
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'include/f2fs_fs.h')
-rw-r--r-- | include/f2fs_fs.h | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 3323be1..b6bd4a7 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -332,6 +332,7 @@ struct device_info { u_int32_t nr_zones; u_int32_t nr_rnd_zones; size_t zone_blocks; + size_t *zone_cap_blocks; }; typedef struct { @@ -537,6 +538,7 @@ struct f2fs_configuration { (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) +#define round_up(x, y) (((x) + (y) - 1) / (y)) /* * Copied from fs/f2fs/f2fs.h */ @@ -1325,13 +1327,42 @@ blk_zone_cond_str(struct blk_zone *blkz) return "Unknown-cond"; } -#define blk_zone_empty(z) (blk_zone_cond(z) == BLK_ZONE_COND_EMPTY) +/* + * Handle kernel zone capacity support + */ +#ifndef HAVE_BLK_ZONE_REP_V2 +#define BLK_ZONE_REP_CAPACITY (1 << 0) +struct blk_zone_v2 { + __u64 start; /* Zone start sector */ + __u64 len; /* Zone length in number of sectors */ + __u64 wp; /* Zone write pointer position */ + __u8 type; /* Zone type */ + __u8 cond; /* Zone condition */ + __u8 non_seq; /* Non-sequential write resources active */ + __u8 reset; /* Reset write pointer recommended */ + __u8 resv[4]; + __u64 capacity; /* Zone capacity in number of sectors */ + __u8 reserved[24]; +}; +#define blk_zone blk_zone_v2 +struct blk_zone_report_v2 { + __u64 sector; + __u32 nr_zones; + __u32 flags; +struct blk_zone zones[0]; +}; +#define blk_zone_report blk_zone_report_v2 +#endif /* HAVE_BLK_ZONE_REP_V2 */ + +#define blk_zone_empty(z) (blk_zone_cond(z) == BLK_ZONE_COND_EMPTY) #define blk_zone_sector(z) (z)->start #define blk_zone_length(z) (z)->len #define blk_zone_wp_sector(z) (z)->wp #define blk_zone_need_reset(z) (int)(z)->reset #define blk_zone_non_seq(z) (int)(z)->non_seq +#define blk_zone_capacity(z, f) ((f & BLK_ZONE_REP_CAPACITY) ? \ + (z)->capacity : (z)->len) #endif @@ -1343,6 +1374,7 @@ extern int f2fs_report_zones(int, report_zones_cb_t *, void *); extern int f2fs_check_zones(int); int f2fs_reset_zone(int, void *); extern int f2fs_reset_zones(int); +extern uint32_t f2fs_get_usable_segments(struct f2fs_super_block *sb); #define SIZE_ALIGN(val, size) ((val) + (size) - 1) / (size) #define SEG_ALIGN(blks) SIZE_ALIGN(blks, c.blks_per_seg) @@ -1353,6 +1385,7 @@ static inline double get_best_overprovision(struct f2fs_super_block *sb) { double reserved, ovp, candidate, end, diff, space; double max_ovp = 0, max_space = 0; + u_int32_t usable_main_segs = f2fs_get_usable_segments(sb); if (get_sb(segment_count_main) < 256) { candidate = 10; @@ -1366,9 +1399,9 @@ static inline double get_best_overprovision(struct f2fs_super_block *sb) for (; candidate <= end; candidate += diff) { reserved = (2 * (100 / candidate + 1) + 6) * - get_sb(segs_per_sec); - ovp = (get_sb(segment_count_main) - reserved) * candidate / 100; - space = get_sb(segment_count_main) - reserved - ovp; + round_up(usable_main_segs, get_sb(section_count)); + ovp = (usable_main_segs - reserved) * candidate / 100; + space = usable_main_segs - reserved - ovp; if (max_space < space) { max_space = space; max_ovp = candidate; |