xfs: hook live realtime rmap operations during a repair operation
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:20 +0000 (14:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:37:19 +0000 (15:37 -0700)
Hook the regular realtime rmap code when an rtrmapbt repair operation is
running so that we can unlock the AGF buffer to scan the filesystem and
keep the in-memory btree up to date during the scan.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/xfs_rmap.c
libxfs/xfs_rmap.h
libxfs/xfs_rtgroup.c
libxfs/xfs_rtgroup.h

index f07561ff8dd5b96bafe29736a159bf788a275e1c..9eff45fcdd6ed151e665783856c0c6c34f1c922e 100644 (file)
@@ -917,8 +917,7 @@ xfs_rmap_update_hook(
                        .oinfo          = *oinfo, /* struct copy */
                };
 
-               if (pag)
-                       xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
+               xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
        }
 }
 
@@ -952,6 +951,50 @@ xfs_rmap_hook_setup(
 # define xfs_rmap_update_hook(t, p, o, s, b, u, oi)    do { } while (0)
 #endif /* CONFIG_XFS_LIVE_HOOKS */
 
+# if defined(CONFIG_XFS_LIVE_HOOKS) && defined(CONFIG_XFS_RT)
+static inline void
+xfs_rtrmap_update_hook(
+       struct xfs_trans                *tp,
+       struct xfs_rtgroup              *rtg,
+       enum xfs_rmap_intent_type       op,
+       xfs_rgblock_t                   startblock,
+       xfs_extlen_t                    blockcount,
+       bool                            unwritten,
+       const struct xfs_owner_info     *oinfo)
+{
+       if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
+               struct xfs_rmap_update_params   p = {
+                       .startblock     = startblock,
+                       .blockcount     = blockcount,
+                       .unwritten      = unwritten,
+                       .oinfo          = *oinfo, /* struct copy */
+               };
+
+               xfs_hooks_call(&rtg->rtg_rmap_update_hooks, op, &p);
+       }
+}
+
+/* Call the specified function during a rt reverse mapping update. */
+int
+xfs_rtrmap_hook_add(
+       struct xfs_rtgroup      *rtg,
+       struct xfs_rmap_hook    *hook)
+{
+       return xfs_hooks_add(&rtg->rtg_rmap_update_hooks, &hook->rmap_hook);
+}
+
+/* Stop calling the specified function during a rt reverse mapping update. */
+void
+xfs_rtrmap_hook_del(
+       struct xfs_rtgroup      *rtg,
+       struct xfs_rmap_hook    *hook)
+{
+       xfs_hooks_del(&rtg->rtg_rmap_update_hooks, &hook->rmap_hook);
+}
+#else
+# define xfs_rtrmap_update_hook(t, r, o, s, b, u, oi)  do { } while (0)
+#endif /* CONFIG_XFS_LIVE_HOOKS && CONFIG_XFS_RT */
+
 /*
  * Remove a reference to an extent in the rmap btree.
  */
@@ -2708,6 +2751,7 @@ xfs_rtrmap_finish_one(
        xfs_rgnumber_t                  rgno;
        xfs_rgblock_t                   bno;
        bool                            unwritten;
+       int                             error;
 
        trace_xfs_rmap_deferred(mp, ri);
 
@@ -2733,8 +2777,14 @@ xfs_rtrmap_finish_one(
        unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
        bno = xfs_rtb_to_rgbno(mp, ri->ri_bmap.br_startblock, &rgno);
 
-       return __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
+       error = __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
                        ri->ri_bmap.br_blockcount, &oinfo, unwritten);
+       if (error)
+               return error;
+
+       xfs_rtrmap_update_hook(tp, ri->ri_rtg, ri->ri_type, bno,
+                       ri->ri_bmap.br_blockcount, unwritten, &oinfo);
+       return 0;
 }
 
 /*
index 82f7505ca27cde1644360ad00c668b181d0b1ec0..430816354e9918319c918760fa5bd0e5fa262368 100644 (file)
@@ -276,6 +276,12 @@ void xfs_rmap_hook_enable(void);
 int xfs_rmap_hook_add(struct xfs_perag *pag, struct xfs_rmap_hook *hook);
 void xfs_rmap_hook_del(struct xfs_perag *pag, struct xfs_rmap_hook *hook);
 void xfs_rmap_hook_setup(struct xfs_rmap_hook *hook, notifier_fn_t mod_fn);
+
+# ifdef CONFIG_XFS_RT
+int xfs_rtrmap_hook_add(struct xfs_rtgroup *rtg, struct xfs_rmap_hook *hook);
+void xfs_rtrmap_hook_del(struct xfs_rtgroup *rtg, struct xfs_rmap_hook *hook);
+# endif /* CONFIG_XFS_RT */
+
 #endif
 
 #endif /* __XFS_RMAP_H__ */
index a7a227c2a20b1314f12c4bfaa29ef277eae813bb..fe4608fca92d593f8da5d10ac524fd5bf16fad21 100644 (file)
@@ -164,6 +164,7 @@ xfs_initialize_rtgroups(
                memset(&rtg->lock_class, 0, sizeof(rtg->lock_class));
                lockdep_register_key(&rtg->lock_class);
                xfs_defer_drain_init(&rtg->rtg_intents_drain);
+               xfs_hooks_init(&rtg->rtg_rmap_update_hooks);
 #endif /* __KERNEL__ */
 
                /* Active ref owned by mount indicates rtgroup is online. */
index 4f8c7fff7829040d4811765470784d098c927376..f9c5f5d549a2afa4dcdf2c3d0454b897ef7bd6b9 100644 (file)
@@ -50,6 +50,9 @@ struct xfs_rtgroup {
         * inconsistencies.
         */
        struct xfs_defer_drain  rtg_intents_drain;
+
+       /* Hook to feed rt rmapbt updates to an active online repair. */
+       struct xfs_hooks        rtg_rmap_update_hooks;
 #endif /* __KERNEL__ */
 };