xfs: consider shutdown in bmapbt cursor delete assert
commit 1cd738b13ae9b29e03d6149f0246c61f76e81fcf upstream. The assert in xfs_btree_del_cursor() checks that the bmapbt block allocation field has been handled correctly before the cursor is freed. This field is used for accurate calculation of indirect block reservation requirements (for delayed allocations), for example. generic/019 reproduces a scenario where this assert fails because the filesystem has shutdown while in the middle of a bmbt record insertion. This occurs after a bmbt block has been allocated via the cursor but before the higher level bmap function (i.e. xfs_bmap_add_extent_hole_real()) completes and resets the field. Update the assert to accommodate the transient state if the filesystem has shutdown. While here, clean up the indentation and comments in the function. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
e3ffe7387c
commit
f1916a88c8
@@ -353,20 +353,17 @@ xfs_btree_free_block(
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xfs_btree_del_cursor(
|
xfs_btree_del_cursor(
|
||||||
xfs_btree_cur_t *cur, /* btree cursor */
|
struct xfs_btree_cur *cur, /* btree cursor */
|
||||||
int error) /* del because of error */
|
int error) /* del because of error */
|
||||||
{
|
{
|
||||||
int i; /* btree level */
|
int i; /* btree level */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the buffer pointers, and release the buffers.
|
* Clear the buffer pointers and release the buffers. If we're doing
|
||||||
* If we're doing this in the face of an error, we
|
* this because of an error, inspect all of the entries in the bc_bufs
|
||||||
* need to make sure to inspect all of the entries
|
* array for buffers to be unlocked. This is because some of the btree
|
||||||
* in the bc_bufs array for buffers to be unlocked.
|
* code works from level n down to 0, and if we get an error along the
|
||||||
* This is because some of the btree code works from
|
* way we won't have initialized all the entries down to 0.
|
||||||
* level n down to 0, and if we get an error along
|
|
||||||
* the way we won't have initialized all the entries
|
|
||||||
* down to 0.
|
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < cur->bc_nlevels; i++) {
|
for (i = 0; i < cur->bc_nlevels; i++) {
|
||||||
if (cur->bc_bufs[i])
|
if (cur->bc_bufs[i])
|
||||||
@@ -374,17 +371,11 @@ xfs_btree_del_cursor(
|
|||||||
else if (!error)
|
else if (!error)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Can't free a bmap cursor without having dealt with the
|
ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || cur->bc_ino.allocated == 0 ||
|
||||||
* allocated indirect blocks' accounting.
|
XFS_FORCED_SHUTDOWN(cur->bc_mp));
|
||||||
*/
|
|
||||||
ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
|
|
||||||
cur->bc_ino.allocated == 0);
|
|
||||||
/*
|
|
||||||
* Free the cursor.
|
|
||||||
*/
|
|
||||||
if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
|
if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
|
||||||
kmem_free((void *)cur->bc_ops);
|
kmem_free(cur->bc_ops);
|
||||||
kmem_cache_free(xfs_btree_cur_zone, cur);
|
kmem_cache_free(xfs_btree_cur_zone, cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user