]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: support RT inodes in xfs_mod_delalloc
authorChristoph Hellwig <hch@lst.de>
Mon, 22 Apr 2024 11:20:15 +0000 (13:20 +0200)
committerChandan Babu R <chandanbabu@kernel.org>
Mon, 22 Apr 2024 12:30:48 +0000 (18:00 +0530)
To prepare for re-enabling delalloc on RT devices, track the data blocks
(which use the RT device when the inode sits on it) and the indirect
blocks (which don't) separately to xfs_mod_delalloc, and add a new
percpu counter to also track the RT delalloc blocks.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/scrub/fscounters.c
fs/xfs/scrub/fscounters.h
fs/xfs/scrub/fscounters_repair.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_super.c

index d7a5ce2e4305af8f7d980644667eb0b728f4f162..a2b715450ec23ef03ec1afc027d2b6b11ea59fc6 100644 (file)
@@ -1977,7 +1977,7 @@ xfs_bmap_add_extent_delay_real(
        }
 
        if (da_new != da_old)
-               xfs_mod_delalloc(mp, (int64_t)da_new - da_old);
+               xfs_mod_delalloc(bma->ip, 0, (int64_t)da_new - da_old);
 
        if (bma->cur) {
                da_new += bma->cur->bc_bmap.allocated;
@@ -2696,7 +2696,7 @@ xfs_bmap_add_extent_hole_delay(
                /*
                 * Nothing to do for disk quota accounting here.
                 */
-               xfs_mod_delalloc(ip->i_mount, (int64_t)newlen - oldlen);
+               xfs_mod_delalloc(ip, 0, (int64_t)newlen - oldlen);
        }
 }
 
@@ -3373,7 +3373,7 @@ xfs_bmap_alloc_account(
                 * yet.
                 */
                if (ap->wasdel) {
-                       xfs_mod_delalloc(ap->ip->i_mount, -(int64_t)ap->length);
+                       xfs_mod_delalloc(ap->ip, -(int64_t)ap->length, 0);
                        return;
                }
 
@@ -3397,7 +3397,7 @@ xfs_bmap_alloc_account(
        xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
        if (ap->wasdel) {
                ap->ip->i_delayed_blks -= ap->length;
-               xfs_mod_delalloc(ap->ip->i_mount, -(int64_t)ap->length);
+               xfs_mod_delalloc(ap->ip, -(int64_t)ap->length, 0);
                fld = isrt ? XFS_TRANS_DQ_DELRTBCOUNT : XFS_TRANS_DQ_DELBCOUNT;
        } else {
                fld = isrt ? XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
@@ -4126,7 +4126,7 @@ xfs_bmapi_reserve_delalloc(
                goto out_unreserve_frextents;
 
        ip->i_delayed_blks += alen;
-       xfs_mod_delalloc(ip->i_mount, alen + indlen);
+       xfs_mod_delalloc(ip, alen, indlen);
 
        got->br_startoff = aoff;
        got->br_startblock = nullstartblock(indlen);
@@ -5024,7 +5024,7 @@ xfs_bmap_del_extent_delay(
                fdblocks += del->br_blockcount;
 
        xfs_add_fdblocks(mp, fdblocks);
-       xfs_mod_delalloc(mp, -(int64_t)fdblocks);
+       xfs_mod_delalloc(ip, -(int64_t)del->br_blockcount, -da_diff);
        return error;
 }
 
index b662e52fe69564891ca53a4a0fe521ea45f7d927..1d3e98346933e1100d951af3ce77618b1d00aa0f 100644 (file)
@@ -412,6 +412,7 @@ xchk_fscount_count_frextents(
        int                     error;
 
        fsc->frextents = 0;
+       fsc->frextents_delayed = 0;
        if (!xfs_has_realtime(mp))
                return 0;
 
@@ -423,6 +424,8 @@ xchk_fscount_count_frextents(
                goto out_unlock;
        }
 
+       fsc->frextents_delayed = percpu_counter_sum(&mp->m_delalloc_rtextents);
+
 out_unlock:
        xfs_rtbitmap_unlock_shared(sc->mp, XFS_RBMLOCK_BITMAP);
        return error;
@@ -434,6 +437,7 @@ xchk_fscount_count_frextents(
        struct xchk_fscounters  *fsc)
 {
        fsc->frextents = 0;
+       fsc->frextents_delayed = 0;
        return 0;
 }
 #endif /* CONFIG_XFS_RT */
@@ -593,7 +597,7 @@ xchk_fscounters(
        }
 
        if (!xchk_fscount_within_range(sc, frextents, &mp->m_frextents,
-                       fsc->frextents)) {
+                       fsc->frextents - fsc->frextents_delayed)) {
                if (fsc->frozen)
                        xchk_set_corrupt(sc);
                else
index 461a13d25f4b38489e71b8bb0fcff8a633385823..bcf56e1c36f91c481897e98b9066d6da65fa1fdd 100644 (file)
@@ -12,6 +12,7 @@ struct xchk_fscounters {
        uint64_t                ifree;
        uint64_t                fdblocks;
        uint64_t                frextents;
+       uint64_t                frextents_delayed;
        unsigned long long      icount_min;
        unsigned long long      icount_max;
        bool                    frozen;
index 94cdb852bee462ab57d1f519a807386b111f5415..469bf645dbea52643a77afd138aff902f34bb207 100644 (file)
@@ -65,7 +65,17 @@ xrep_fscounters(
        percpu_counter_set(&mp->m_icount, fsc->icount);
        percpu_counter_set(&mp->m_ifree, fsc->ifree);
        percpu_counter_set(&mp->m_fdblocks, fsc->fdblocks);
-       percpu_counter_set(&mp->m_frextents, fsc->frextents);
+
+       /*
+        * Online repair is only supported on v5 file systems, which require
+        * lazy sb counters and thus no update of sb_fdblocks here.  But as of
+        * now we don't support lazy counting sb_frextents yet, and thus need
+        * to also update it directly here.  And for that we need to keep
+        * track of the delalloc reservations separately, as they are are
+        * subtracted from m_frextents, but not included in sb_frextents.
+        */
+       percpu_counter_set(&mp->m_frextents,
+               fsc->frextents - fsc->frextents_delayed);
        mp->m_sb.sb_frextents = fsc->frextents;
 
        return 0;
index b9df7cc9c473dd3678fd161fe18d19272183a912..b2e5653b5200cb4ed3ea1dc1271bfaa7e243a7d1 100644 (file)
@@ -34,6 +34,7 @@
 #include "xfs_health.h"
 #include "xfs_trace.h"
 #include "xfs_ag.h"
+#include "xfs_rtbitmap.h"
 #include "scrub/stats.h"
 
 static DEFINE_MUTEX(xfs_uuid_table_mutex);
@@ -1408,9 +1409,20 @@ xfs_clear_incompat_log_features(
 #define XFS_DELALLOC_BATCH     (4096)
 void
 xfs_mod_delalloc(
-       struct xfs_mount        *mp,
-       int64_t                 delta)
+       struct xfs_inode        *ip,
+       int64_t                 data_delta,
+       int64_t                 ind_delta)
 {
-       percpu_counter_add_batch(&mp->m_delalloc_blks, delta,
+       struct xfs_mount        *mp = ip->i_mount;
+
+       if (XFS_IS_REALTIME_INODE(ip)) {
+               percpu_counter_add_batch(&mp->m_delalloc_rtextents,
+                               xfs_rtb_to_rtx(mp, data_delta),
+                               XFS_DELALLOC_BATCH);
+               if (!ind_delta)
+                       return;
+               data_delta = 0;
+       }
+       percpu_counter_add_batch(&mp->m_delalloc_blks, data_delta + ind_delta,
                        XFS_DELALLOC_BATCH);
 }
index 3a985c2ff06fe5c0ab700328e6d4bd05f5cb568b..ca6f105990a2c3ca67020f946f4a7a82234dddfb 100644 (file)
@@ -195,6 +195,12 @@ typedef struct xfs_mount {
         * extents or anything related to the rt device.
         */
        struct percpu_counter   m_delalloc_blks;
+
+       /*
+        * RT version of the above.
+        */
+       struct percpu_counter   m_delalloc_rtextents;
+
        /*
         * Global count of allocation btree blocks in use across all AGs. Only
         * used when perag reservation is enabled. Helps prevent block
@@ -605,6 +611,7 @@ struct xfs_error_cfg * xfs_error_get_cfg(struct xfs_mount *mp,
 void xfs_force_summary_recalc(struct xfs_mount *mp);
 int xfs_add_incompat_log_feature(struct xfs_mount *mp, uint32_t feature);
 bool xfs_clear_incompat_log_features(struct xfs_mount *mp);
-void xfs_mod_delalloc(struct xfs_mount *mp, int64_t delta);
+void xfs_mod_delalloc(struct xfs_inode *ip, int64_t data_delta,
+               int64_t ind_delta);
 
 #endif /* __XFS_MOUNT_H__ */
index ed4a2f8c1936fb394d17fea26269f710d97e8995..e525a6c477ff91c7165877887725fed0bf05d0b3 100644 (file)
@@ -1052,12 +1052,18 @@ xfs_init_percpu_counters(
        if (error)
                goto free_fdblocks;
 
-       error = percpu_counter_init(&mp->m_frextents, 0, GFP_KERNEL);
+       error = percpu_counter_init(&mp->m_delalloc_rtextents, 0, GFP_KERNEL);
        if (error)
                goto free_delalloc;
 
+       error = percpu_counter_init(&mp->m_frextents, 0, GFP_KERNEL);
+       if (error)
+               goto free_delalloc_rt;
+
        return 0;
 
+free_delalloc_rt:
+       percpu_counter_destroy(&mp->m_delalloc_rtextents);
 free_delalloc:
        percpu_counter_destroy(&mp->m_delalloc_blks);
 free_fdblocks:
@@ -1086,6 +1092,9 @@ xfs_destroy_percpu_counters(
        percpu_counter_destroy(&mp->m_icount);
        percpu_counter_destroy(&mp->m_ifree);
        percpu_counter_destroy(&mp->m_fdblocks);
+       ASSERT(xfs_is_shutdown(mp) ||
+              percpu_counter_sum(&mp->m_delalloc_rtextents) == 0);
+       percpu_counter_destroy(&mp->m_delalloc_rtextents);
        ASSERT(xfs_is_shutdown(mp) ||
               percpu_counter_sum(&mp->m_delalloc_blks) == 0);
        percpu_counter_destroy(&mp->m_delalloc_blks);