]> git.baikalelectronics.ru Git - kernel.git/commitdiff
zonefs: Fix active zone accounting
authorDamien Le Moal <damien.lemoal@opensource.wdc.com>
Mon, 21 Nov 2022 07:29:37 +0000 (16:29 +0900)
committerDamien Le Moal <damien.lemoal@opensource.wdc.com>
Fri, 25 Nov 2022 08:01:22 +0000 (17:01 +0900)
If a file zone transitions to the offline or readonly state from an
active state, we must clear the zone active flag and decrement the
active seq file counter. Do so in zonefs_account_active() using the new
zonefs inode flags ZONEFS_ZONE_OFFLINE and ZONEFS_ZONE_READONLY. These
flags are set if necessary in zonefs_check_zone_condition() based on the
result of report zones operation after an IO error.

Fixes: 87c9ce3ffec9 ("zonefs: Add active seq file accounting")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
fs/zonefs/super.c
fs/zonefs/zonefs.h

index f0e8a000f07363247703d9783a74249cd781f176..2c53fbb8d918e5ca63ab3a620455b1f173883251 100644 (file)
@@ -40,6 +40,13 @@ static void zonefs_account_active(struct inode *inode)
        if (zi->i_ztype != ZONEFS_ZTYPE_SEQ)
                return;
 
+       /*
+        * For zones that transitioned to the offline or readonly condition,
+        * we only need to clear the active state.
+        */
+       if (zi->i_flags & (ZONEFS_ZONE_OFFLINE | ZONEFS_ZONE_READONLY))
+               goto out;
+
        /*
         * If the zone is active, that is, if it is explicitly open or
         * partially written, check if it was already accounted as active.
@@ -53,6 +60,7 @@ static void zonefs_account_active(struct inode *inode)
                return;
        }
 
+out:
        /* The zone is not active. If it was, update the active count */
        if (zi->i_flags & ZONEFS_ZONE_ACTIVE) {
                zi->i_flags &= ~ZONEFS_ZONE_ACTIVE;
@@ -324,6 +332,7 @@ static loff_t zonefs_check_zone_condition(struct inode *inode,
                inode->i_flags |= S_IMMUTABLE;
                inode->i_mode &= ~0777;
                zone->wp = zone->start;
+               zi->i_flags |= ZONEFS_ZONE_OFFLINE;
                return 0;
        case BLK_ZONE_COND_READONLY:
                /*
@@ -342,8 +351,10 @@ static loff_t zonefs_check_zone_condition(struct inode *inode,
                        zone->cond = BLK_ZONE_COND_OFFLINE;
                        inode->i_mode &= ~0777;
                        zone->wp = zone->start;
+                       zi->i_flags |= ZONEFS_ZONE_OFFLINE;
                        return 0;
                }
+               zi->i_flags |= ZONEFS_ZONE_READONLY;
                inode->i_mode &= ~0222;
                return i_size_read(inode);
        case BLK_ZONE_COND_FULL:
index 4b3de66c323342ab8ac10f4691e492197e7e6998..1dbe78119ff163fcd5b63243299735767e51576f 100644 (file)
@@ -39,8 +39,10 @@ static inline enum zonefs_ztype zonefs_zone_type(struct blk_zone *zone)
        return ZONEFS_ZTYPE_SEQ;
 }
 
-#define ZONEFS_ZONE_OPEN       (1 << 0)
-#define ZONEFS_ZONE_ACTIVE     (1 << 1)
+#define ZONEFS_ZONE_OPEN       (1U << 0)
+#define ZONEFS_ZONE_ACTIVE     (1U << 1)
+#define ZONEFS_ZONE_OFFLINE    (1U << 2)
+#define ZONEFS_ZONE_READONLY   (1U << 3)
 
 /*
  * In-memory inode data.