libxfs: add missing agfl free deferred op type
RFC PATCH 1/1 libxfs: add missing agfl free deferred op type
Soo... I tried to run xfs_repair in gdb on arekm's big filesystem, but we forgot to port deferred agfl free defer ops type to xfsprogs so it blew up earlier this afternoon. This is a patch to add it in, but since it takes a while to get far enough to start rebuilding directories, this is basically an untested patch.
Which I'm sending out in case sandeen/dchinner are doing the same thing I am. :P
--D
---
From: Darrick J. Wong <[email protected]>
When we added a new defer op type for agfl block freeing to the kernel, we forgot to add that type to the userspace side of things. This will cause spontaneous combustion in xfs_repair if we try to rebuild directories.
--- libxfs/defer_item.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
libxfs/defer_item.c +44 -0
@@ -118,11 +118,55 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = { .cancel_item = xfs_extent_free_cancel_item, }; +/* +* AGFL blocks are accounted differently in the reserve pools and are not +* inserted into the busy extent list. +*/ +STATIC int +xfs_agfl_free_finish_item ( +struct xfs_trans *tp, +struct list_head *item, +void *done_item, +void **state) +{ +struct xfs_mount *mp = tp->t_mountp; +struct xfs_extent_free_item *free; +struct xfs_buf *agbp; +int error; +xfs_agnumber_t agno; +xfs_agblock_t agbno; + + free = container_of(item, struct xfs_extent_free_item, xefi_list); +ASSERT (free->xefi_blockcount ==1 ); + agno =XFS_FSB_TO_AGNO (mp, free->xefi_startblock); + agbno =XFS_FSB_TO_AGBNO (mp, free->xefi_startblock); + + error =xfs_alloc_read_agf (mp, tp, agno,0 , &agbp); +if (!error) + error =xfs_free_agfl_block (tp, agno, agbno, agbp, + &free->xefi_oinfo); +kmem_free (free); +return error; +} + +/* sub-type with special handling for AGFL deferred frees */ +static const struct xfs_defer_op_type xfs_agfl_free_defer_type = { + .type =XFS_DEFER_OPS_TYPE_AGFL_FREE , + .diff_items = xfs_extent_free_diff_items, + .create_intent = xfs_extent_free_create_intent, + .abort_intent = xfs_extent_free_abort_intent, + .log_item = xfs_extent_free_log_item, + .create_done = xfs_extent_free_create_done, + .finish_item = xfs_agfl_free_finish_item, + .cancel_item = xfs_extent_free_cancel_item, +}; +/* Register the deferred op type. */ void xfs_extent_free_init_defer_op (void ) {xfs_defer_init_op_type (&xfs_extent_free_defer_type); +xfs_defer_init_op_type (&xfs_agfl_free_defer_type); }/* Reverse Mapping */
Quoted 8 lines · Darrick J. Wong
Soo... I tried to run
xfs_repairin gdb on arekm's big filesystem, but we forgot to port deferred agfl free defer ops type to xfsprogs so it blew up earlier this afternoon. This is a patch to add it in, but since it takes a while to get far enough to start rebuilding directories, this is basically an untested patch.Which I'm sending out in case sandeen/dchinner are doing the same thing I am. :P
FWIW this has now passed the usual testing, so strike the 'RFC' from the title.
--D
Quoted 76 lines
--D
---
From: Darrick J. Wong <[email protected]>When we added a new defer op type for agfl block freeing to the kernel, we forgot to add that type to the userspace side of things. This will cause spontaneous combustion in
xfs_repairif we try to rebuild directories.Fixes d5c1b462232 ("xfs: defer agfl block frees when dfops is available")Signed-off-by Darrick J. Wong <[email protected]>--- libxfs/defer_item.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)libxfs/defer_item.c +44
-0@@ -118,11 +118,55 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = { .cancel_item = xfs_extent_free_cancel_item, }; +/* +* AGFL blocks are accounted differently in the reserve pools and are not +* inserted into the busy extent list. +*/ +STATIC int +xfs_agfl_free_finish_item ( +struct xfs_trans *tp, +struct list_head *item, +void *done_item, +void **state) +{ +struct xfs_mount *mp = tp->t_mountp; +struct xfs_extent_free_item *free; +struct xfs_buf *agbp; +int error; +xfs_agnumber_t agno; +xfs_agblock_t agbno; + + free = container_of(item, struct xfs_extent_free_item, xefi_list); +ASSERT (free->xefi_blockcount ==1 ); + agno =XFS_FSB_TO_AGNO (mp, free->xefi_startblock); + agbno =XFS_FSB_TO_AGBNO (mp, free->xefi_startblock); + + error =xfs_alloc_read_agf (mp, tp, agno,0 , &agbp); +if (!error) + error =xfs_free_agfl_block (tp, agno, agbno, agbp, + &free->xefi_oinfo); +kmem_free (free); +return error; +} + +/* sub-type with special handling for AGFL deferred frees */ +static const struct xfs_defer_op_type xfs_agfl_free_defer_type = { + .type =XFS_DEFER_OPS_TYPE_AGFL_FREE , + .diff_items = xfs_extent_free_diff_items, + .create_intent = xfs_extent_free_create_intent, + .abort_intent = xfs_extent_free_abort_intent, + .log_item = xfs_extent_free_log_item, + .create_done = xfs_extent_free_create_done, + .finish_item = xfs_agfl_free_finish_item, + .cancel_item = xfs_extent_free_cancel_item, +}; +/* Register the deferred op type. */ void xfs_extent_free_init_defer_op (void ) {xfs_defer_init_op_type (&xfs_extent_free_defer_type); +xfs_defer_init_op_type (&xfs_agfl_free_defer_type); }/* Reverse Mapping */
Quoted 14 lines · Darrick J. Wong
Soo... I tried to run
xfs_repairin gdb on arekm's big filesystem, but we forgot to port deferred agfl free defer ops type to xfsprogs so it blew up earlier this afternoon. This is a patch to add it in, but since it takes a while to get far enough to start rebuilding directories, this is basically an untested patch.Which I'm sending out in case sandeen/dchinner are doing the same thing I am. :P
--D
---
From: Darrick J. Wong <[email protected]>
Quoted 7 lines
When we added a new defer op type for agfl block freeing to the kernel, we forgot to add that type to the userspace side of things. This will cause spontaneous combustion in
xfs_repairif we try to rebuild directories.Fixes d5c1b462232 ("xfs: defer agfl block frees when dfops is available")Signed-off-by Darrick J. Wong <[email protected]>
I did review this and then other stuff started taking my attention. :D
I'll run it through my testing as well, thanks.
Quoted 65 lines
--- libxfs/defer_item.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)libxfs/defer_item.c +44
-0@@ -118,11 +118,55 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = { .cancel_item = xfs_extent_free_cancel_item, }; +/* +* AGFL blocks are accounted differently in the reserve pools and are not +* inserted into the busy extent list. +*/ +STATIC int +xfs_agfl_free_finish_item ( +struct xfs_trans *tp, +struct list_head *item, +void *done_item, +void **state) +{ +struct xfs_mount *mp = tp->t_mountp; +struct xfs_extent_free_item *free; +struct xfs_buf *agbp; +int error; +xfs_agnumber_t agno; +xfs_agblock_t agbno; + + free = container_of(item, struct xfs_extent_free_item, xefi_list); +ASSERT (free->xefi_blockcount ==1 ); + agno =XFS_FSB_TO_AGNO (mp, free->xefi_startblock); + agbno =XFS_FSB_TO_AGBNO (mp, free->xefi_startblock); + + error =xfs_alloc_read_agf (mp, tp, agno,0 , &agbp); +if (!error) + error =xfs_free_agfl_block (tp, agno, agbno, agbp, + &free->xefi_oinfo); +kmem_free (free); +return error; +} + +/* sub-type with special handling for AGFL deferred frees */ +static const struct xfs_defer_op_type xfs_agfl_free_defer_type = { + .type =XFS_DEFER_OPS_TYPE_AGFL_FREE , + .diff_items = xfs_extent_free_diff_items, + .create_intent = xfs_extent_free_create_intent, + .abort_intent = xfs_extent_free_abort_intent, + .log_item = xfs_extent_free_log_item, + .create_done = xfs_extent_free_create_done, + .finish_item = xfs_agfl_free_finish_item, + .cancel_item = xfs_extent_free_cancel_item, +}; +/* Register the deferred op type. */ void xfs_extent_free_init_defer_op (void ) {xfs_defer_init_op_type (&xfs_extent_free_defer_type); +xfs_defer_init_op_type (&xfs_agfl_free_defer_type); }/* Reverse Mapping */