f2fs: let's finish or reset zones all the time
authorJaegeuk Kim <jaegeuk@kernel.org>
Sat, 2 Dec 2023 18:16:24 +0000 (10:16 -0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 5 Dec 2023 19:29:05 +0000 (11:29 -0800)
In order to limit # of open zones, let's finish or reset zones given # of
valid blocks per section and its zone condition.

Reviewed-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/segment.c

index 9081c9af977a9d6274a0c4d3ff88b0d3faf569f1..007ebb10723662a859dabb0c81a7f61348d6100a 100644 (file)
@@ -4870,82 +4870,43 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
                                    struct f2fs_dev_info *fdev,
                                    struct blk_zone *zone)
 {
-       unsigned int wp_segno, wp_blkoff, zone_secno, zone_segno, segno;
-       block_t zone_block, wp_block, last_valid_block;
+       unsigned int zone_segno;
+       block_t zone_block, valid_block_cnt;
        unsigned int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT;
-       int i, s, b, ret;
-       struct seg_entry *se;
+       int ret;
 
        if (zone->type != BLK_ZONE_TYPE_SEQWRITE_REQ)
                return 0;
 
-       wp_block = fdev->start_blk + (zone->wp >> log_sectors_per_block);
-       wp_segno = GET_SEGNO(sbi, wp_block);
-       wp_blkoff = wp_block - START_BLOCK(sbi, wp_segno);
        zone_block = fdev->start_blk + (zone->start >> log_sectors_per_block);
        zone_segno = GET_SEGNO(sbi, zone_block);
-       zone_secno = GET_SEC_FROM_SEG(sbi, zone_segno);
-
-       if (zone_segno >= MAIN_SEGS(sbi))
-               return 0;
 
        /*
         * Skip check of zones cursegs point to, since
         * fix_curseg_write_pointer() checks them.
         */
-       for (i = 0; i < NO_CHECK_TYPE; i++)
-               if (zone_secno == GET_SEC_FROM_SEG(sbi,
-                                                  CURSEG_I(sbi, i)->segno))
-                       return 0;
+       if (zone_segno >= MAIN_SEGS(sbi) ||
+           IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, zone_segno)))
+               return 0;
 
        /*
-        * Get last valid block of the zone.
+        * Get # of valid block of the zone.
         */
-       last_valid_block = zone_block - 1;
-       for (s = sbi->segs_per_sec - 1; s >= 0; s--) {
-               segno = zone_segno + s;
-               se = get_seg_entry(sbi, segno);
-               for (b = sbi->blocks_per_seg - 1; b >= 0; b--)
-                       if (f2fs_test_bit(b, se->cur_valid_map)) {
-                               last_valid_block = START_BLOCK(sbi, segno) + b;
-                               break;
-                       }
-               if (last_valid_block >= zone_block)
-                       break;
-       }
+       valid_block_cnt = get_valid_blocks(sbi, zone_segno, true);
 
-       /*
-        * When safely unmounted in the previous mount, we can trust write
-        * pointers. Otherwise, finish zones.
-        */
-       if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
-               /*
-                * The write pointer matches with the valid blocks or
-                * already points to the end of the zone.
-                */
-               if ((last_valid_block + 1 == wp_block) ||
-                               (zone->wp == zone->start + zone->len))
-                       return 0;
-       }
+       if ((!valid_block_cnt && zone->cond == BLK_ZONE_COND_EMPTY) ||
+           (valid_block_cnt && zone->cond == BLK_ZONE_COND_FULL))
+               return 0;
 
-       if (last_valid_block + 1 == zone_block) {
-               if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
-                       /*
-                        * If there is no valid block in the zone and if write
-                        * pointer is not at zone start, reset the write
-                        * pointer.
-                        */
-                       f2fs_notice(sbi,
-                             "Zone without valid block has non-zero write "
-                             "pointer. Reset the write pointer: wp[0x%x,0x%x]",
-                             wp_segno, wp_blkoff);
-               }
+       if (!valid_block_cnt) {
+               f2fs_notice(sbi, "Zone without valid block has non-zero write "
+                           "pointer. Reset the write pointer: cond[0x%x]",
+                           zone->cond);
                ret = __f2fs_issue_discard_zone(sbi, fdev->bdev, zone_block,
                                        zone->len >> log_sectors_per_block);
                if (ret)
                        f2fs_err(sbi, "Discard zone failed: %s (errno=%d)",
                                 fdev->path, ret);
-
                return ret;
        }
 
@@ -4957,10 +4918,8 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
         * selected for write operation until it get discarded.
         */
        f2fs_notice(sbi, "Valid blocks are not aligned with write "
-                           "pointer: valid block[0x%x,0x%x] wp[0x%x,0x%x]",
-                           GET_SEGNO(sbi, last_valid_block),
-                           GET_BLKOFF_FROM_SEG0(sbi, last_valid_block),
-                           wp_segno, wp_blkoff);
+                   "pointer: valid block[0x%x,0x%x] cond[0x%x]",
+                   zone_segno, valid_block_cnt, zone->cond);
 
        ret = blkdev_zone_mgmt(fdev->bdev, REQ_OP_ZONE_FINISH,
                                zone->start, zone->len, GFP_NOFS);