On Thu, Jun 26, 2025 at 08:48:59AM +1000, Dave Chinner wrote: > From: Dave Chinner <dchinner@xxxxxxxxxx> > > The stale buffer item completion handling is currently only done > from BLI unpinning. We need to perform this function from where-ever > the last reference to the BLI is dropped, so first we need to > factor this code out into a helper. > > Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> Reviewed-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx> > --- > fs/xfs/xfs_buf_item.c | 60 ++++++++++++++++++++++++++----------------- > 1 file changed, 37 insertions(+), 23 deletions(-) > > diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c > index 3e3c0f65a25c..c95826863c82 100644 > --- a/fs/xfs/xfs_buf_item.c > +++ b/fs/xfs/xfs_buf_item.c > @@ -444,6 +444,42 @@ xfs_buf_item_pin( > atomic_inc(&bip->bli_buf->b_pin_count); > } > > +/* > + * For a stale BLI, process all the necessary completions that must be > + * performed when the final BLI reference goes away. The buffer will be > + * referenced and locked here - we return to the caller with the buffer still > + * referenced and locked for them to finalise processing of the buffer. > + */ > +static void > +xfs_buf_item_finish_stale( > + struct xfs_buf_log_item *bip) > +{ > + struct xfs_buf *bp = bip->bli_buf; > + struct xfs_log_item *lip = &bip->bli_item; > + > + ASSERT(bip->bli_flags & XFS_BLI_STALE); > + ASSERT(xfs_buf_islocked(bp)); > + ASSERT(bp->b_flags & XBF_STALE); > + ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); > + ASSERT(list_empty(&lip->li_trans)); > + ASSERT(!bp->b_transp); > + > + if (bip->bli_flags & XFS_BLI_STALE_INODE) { > + xfs_buf_item_done(bp); > + xfs_buf_inode_iodone(bp); > + ASSERT(list_empty(&bp->b_li_list)); > + return; > + } > + > + /* > + * We may or may not be on the AIL here, xfs_trans_ail_delete() will do > + * the right thing regardless of the situation in which we are called. > + */ > + xfs_trans_ail_delete(lip, SHUTDOWN_LOG_IO_ERROR); > + xfs_buf_item_relse(bip); > + ASSERT(bp->b_log_item == NULL); > +} > + > /* > * This is called to unpin the buffer associated with the buf log item which was > * previously pinned with a call to xfs_buf_item_pin(). We enter this function > @@ -493,13 +529,6 @@ xfs_buf_item_unpin( > } > > if (stale) { > - ASSERT(bip->bli_flags & XFS_BLI_STALE); > - ASSERT(xfs_buf_islocked(bp)); > - ASSERT(bp->b_flags & XBF_STALE); > - ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); > - ASSERT(list_empty(&lip->li_trans)); > - ASSERT(!bp->b_transp); > - > trace_xfs_buf_item_unpin_stale(bip); > > /* > @@ -510,22 +539,7 @@ xfs_buf_item_unpin( > * processing is complete. > */ > xfs_buf_rele(bp); > - > - /* > - * If we get called here because of an IO error, we may or may > - * not have the item on the AIL. xfs_trans_ail_delete() will > - * take care of that situation. xfs_trans_ail_delete() drops > - * the AIL lock. > - */ > - if (bip->bli_flags & XFS_BLI_STALE_INODE) { > - xfs_buf_item_done(bp); > - xfs_buf_inode_iodone(bp); > - ASSERT(list_empty(&bp->b_li_list)); > - } else { > - xfs_trans_ail_delete(lip, SHUTDOWN_LOG_IO_ERROR); > - xfs_buf_item_relse(bip); > - ASSERT(bp->b_log_item == NULL); > - } > + xfs_buf_item_finish_stale(bip); > xfs_buf_relse(bp); > return; > } > -- > 2.45.2 > >