aboutsummaryrefslogtreecommitdiff
path: root/include/f2fs_fs.h
diff options
context:
space:
mode:
authorAravind Ramesh <aravind.ramesh@wdc.com>2020-07-21 22:08:11 +0530
committerJaegeuk Kim <jaegeuk@kernel.org>2020-08-20 09:08:34 -0700
commitf8410857b7a81b1b347253fcca713d8b105e9e7b (patch)
treeaeb1c1ab70c8d7c9b872d9bfe2846ca440e4d14b /include/f2fs_fs.h
parent1e3dd7ae5de14b641c6717cb462fd139351d41f3 (diff)
downloadf2fs-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.h41
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;