@@ -821,6 +821,86 @@ xfs_rmap_unmap(
821821 return error ;
822822}
823823
824+ #ifdef CONFIG_XFS_LIVE_HOOKS
825+ /*
826+ * Use a static key here to reduce the overhead of rmapbt live updates. If
827+ * the compiler supports jump labels, the static branch will be replaced by a
828+ * nop sled when there are no hook users. Online fsck is currently the only
829+ * caller, so this is a reasonable tradeoff.
830+ *
831+ * Note: Patching the kernel code requires taking the cpu hotplug lock. Other
832+ * parts of the kernel allocate memory with that lock held, which means that
833+ * XFS callers cannot hold any locks that might be used by memory reclaim or
834+ * writeback when calling the static_branch_{inc,dec} functions.
835+ */
836+ DEFINE_STATIC_XFS_HOOK_SWITCH (xfs_rmap_hooks_switch );
837+
838+ void
839+ xfs_rmap_hook_disable (void )
840+ {
841+ xfs_hooks_switch_off (& xfs_rmap_hooks_switch );
842+ }
843+
844+ void
845+ xfs_rmap_hook_enable (void )
846+ {
847+ xfs_hooks_switch_on (& xfs_rmap_hooks_switch );
848+ }
849+
850+ /* Call downstream hooks for a reverse mapping update. */
851+ static inline void
852+ xfs_rmap_update_hook (
853+ struct xfs_trans * tp ,
854+ struct xfs_perag * pag ,
855+ enum xfs_rmap_intent_type op ,
856+ xfs_agblock_t startblock ,
857+ xfs_extlen_t blockcount ,
858+ bool unwritten ,
859+ const struct xfs_owner_info * oinfo )
860+ {
861+ if (xfs_hooks_switched_on (& xfs_rmap_hooks_switch )) {
862+ struct xfs_rmap_update_params p = {
863+ .startblock = startblock ,
864+ .blockcount = blockcount ,
865+ .unwritten = unwritten ,
866+ .oinfo = * oinfo , /* struct copy */
867+ };
868+
869+ if (pag )
870+ xfs_hooks_call (& pag -> pag_rmap_update_hooks , op , & p );
871+ }
872+ }
873+
874+ /* Call the specified function during a reverse mapping update. */
875+ int
876+ xfs_rmap_hook_add (
877+ struct xfs_perag * pag ,
878+ struct xfs_rmap_hook * hook )
879+ {
880+ return xfs_hooks_add (& pag -> pag_rmap_update_hooks , & hook -> rmap_hook );
881+ }
882+
883+ /* Stop calling the specified function during a reverse mapping update. */
884+ void
885+ xfs_rmap_hook_del (
886+ struct xfs_perag * pag ,
887+ struct xfs_rmap_hook * hook )
888+ {
889+ xfs_hooks_del (& pag -> pag_rmap_update_hooks , & hook -> rmap_hook );
890+ }
891+
892+ /* Configure rmap update hook functions. */
893+ void
894+ xfs_rmap_hook_setup (
895+ struct xfs_rmap_hook * hook ,
896+ notifier_fn_t mod_fn )
897+ {
898+ xfs_hook_setup (& hook -> rmap_hook , mod_fn );
899+ }
900+ #else
901+ # define xfs_rmap_update_hook (t , p , o , s , b , u , oi ) do { } while (0)
902+ #endif /* CONFIG_XFS_LIVE_HOOKS */
903+
824904/*
825905 * Remove a reference to an extent in the rmap btree.
826906 */
@@ -841,7 +921,7 @@ xfs_rmap_free(
841921 return 0 ;
842922
843923 cur = xfs_rmapbt_init_cursor (mp , tp , agbp , pag );
844-
924+ xfs_rmap_update_hook ( tp , pag , XFS_RMAP_UNMAP , bno , len , false, oinfo );
845925 error = xfs_rmap_unmap (cur , bno , len , false, oinfo );
846926
847927 xfs_btree_del_cursor (cur , error );
@@ -1093,6 +1173,7 @@ xfs_rmap_alloc(
10931173 return 0 ;
10941174
10951175 cur = xfs_rmapbt_init_cursor (mp , tp , agbp , pag );
1176+ xfs_rmap_update_hook (tp , pag , XFS_RMAP_MAP , bno , len , false, oinfo );
10961177 error = xfs_rmap_map (cur , bno , len , false, oinfo );
10971178
10981179 xfs_btree_del_cursor (cur , error );
@@ -2508,6 +2589,38 @@ xfs_rmap_finish_one_cleanup(
25082589 xfs_trans_brelse (tp , agbp );
25092590}
25102591
2592+ /* Commit an rmap operation into the ondisk tree. */
2593+ int
2594+ __xfs_rmap_finish_intent (
2595+ struct xfs_btree_cur * rcur ,
2596+ enum xfs_rmap_intent_type op ,
2597+ xfs_agblock_t bno ,
2598+ xfs_extlen_t len ,
2599+ const struct xfs_owner_info * oinfo ,
2600+ bool unwritten )
2601+ {
2602+ switch (op ) {
2603+ case XFS_RMAP_ALLOC :
2604+ case XFS_RMAP_MAP :
2605+ return xfs_rmap_map (rcur , bno , len , unwritten , oinfo );
2606+ case XFS_RMAP_MAP_SHARED :
2607+ return xfs_rmap_map_shared (rcur , bno , len , unwritten , oinfo );
2608+ case XFS_RMAP_FREE :
2609+ case XFS_RMAP_UNMAP :
2610+ return xfs_rmap_unmap (rcur , bno , len , unwritten , oinfo );
2611+ case XFS_RMAP_UNMAP_SHARED :
2612+ return xfs_rmap_unmap_shared (rcur , bno , len , unwritten , oinfo );
2613+ case XFS_RMAP_CONVERT :
2614+ return xfs_rmap_convert (rcur , bno , len , !unwritten , oinfo );
2615+ case XFS_RMAP_CONVERT_SHARED :
2616+ return xfs_rmap_convert_shared (rcur , bno , len , !unwritten ,
2617+ oinfo );
2618+ default :
2619+ ASSERT (0 );
2620+ return - EFSCORRUPTED ;
2621+ }
2622+ }
2623+
25112624/*
25122625 * Process one of the deferred rmap operations. We pass back the
25132626 * btree cursor to maintain our lock on the rmapbt between calls.
@@ -2574,39 +2687,14 @@ xfs_rmap_finish_one(
25742687 unwritten = ri -> ri_bmap .br_state == XFS_EXT_UNWRITTEN ;
25752688 bno = XFS_FSB_TO_AGBNO (rcur -> bc_mp , ri -> ri_bmap .br_startblock );
25762689
2577- switch (ri -> ri_type ) {
2578- case XFS_RMAP_ALLOC :
2579- case XFS_RMAP_MAP :
2580- error = xfs_rmap_map (rcur , bno , ri -> ri_bmap .br_blockcount ,
2581- unwritten , & oinfo );
2582- break ;
2583- case XFS_RMAP_MAP_SHARED :
2584- error = xfs_rmap_map_shared (rcur , bno ,
2585- ri -> ri_bmap .br_blockcount , unwritten , & oinfo );
2586- break ;
2587- case XFS_RMAP_FREE :
2588- case XFS_RMAP_UNMAP :
2589- error = xfs_rmap_unmap (rcur , bno , ri -> ri_bmap .br_blockcount ,
2590- unwritten , & oinfo );
2591- break ;
2592- case XFS_RMAP_UNMAP_SHARED :
2593- error = xfs_rmap_unmap_shared (rcur , bno ,
2594- ri -> ri_bmap .br_blockcount , unwritten , & oinfo );
2595- break ;
2596- case XFS_RMAP_CONVERT :
2597- error = xfs_rmap_convert (rcur , bno , ri -> ri_bmap .br_blockcount ,
2598- !unwritten , & oinfo );
2599- break ;
2600- case XFS_RMAP_CONVERT_SHARED :
2601- error = xfs_rmap_convert_shared (rcur , bno ,
2602- ri -> ri_bmap .br_blockcount , !unwritten , & oinfo );
2603- break ;
2604- default :
2605- ASSERT (0 );
2606- error = - EFSCORRUPTED ;
2607- }
2690+ error = __xfs_rmap_finish_intent (rcur , ri -> ri_type , bno ,
2691+ ri -> ri_bmap .br_blockcount , & oinfo , unwritten );
2692+ if (error )
2693+ return error ;
26082694
2609- return error ;
2695+ xfs_rmap_update_hook (tp , ri -> ri_pag , ri -> ri_type , bno ,
2696+ ri -> ri_bmap .br_blockcount , unwritten , & oinfo );
2697+ return 0 ;
26102698}
26112699
26122700/*
0 commit comments