diff mbox series

[1/2] xfs: remove the leftover xfs_{set,clear}_li_failed infrastructure

Message ID 20250320075221.1505190-2-hch@lst.de (mailing list archive)
State New
Headers show
Series [1/2] xfs: remove the leftover xfs_{set,clear}_li_failed infrastructure | expand

Commit Message

hch March 20, 2025, 7:52 a.m. UTC
Marking a log item as failed kept a buffer reference around for
resubmission of inode and dquote items.

For inode items commit 298f7bec503f3 ("xfs: pin inode backing buffer to
the inode log item") started pinning the inode item buffers
unconditionally and removed the need for this.  Later commit acc8f8628c37
("xfs: attach dquot buffer to dquot log item buffer") did the same for
dquot items but didn't fully clean up the xfs_clear_li_failed side
for them.  Stop adding the extra pin for dquot items and remove the
helpers.

This happens to fix a call to xfs_buf_free with the AIL lock held,
which would be incorrect for the unlikely case freeing the buffer
ends up calling vfree.

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_dquot.c      |  3 +--
 fs/xfs/xfs_inode_item.c |  6 ------
 fs/xfs/xfs_trans_ail.c  |  5 ++---
 fs/xfs/xfs_trans_priv.h | 28 ----------------------------
 4 files changed, 3 insertions(+), 39 deletions(-)

Comments

Carlos Maiolino March 21, 2025, 9:13 a.m. UTC | #1
On Thu, Mar 20, 2025 at 08:52:13AM +0100, Christoph Hellwig wrote:
> Marking a log item as failed kept a buffer reference around for
> resubmission of inode and dquote items.
> 
> For inode items commit 298f7bec503f3 ("xfs: pin inode backing buffer to
> the inode log item") started pinning the inode item buffers
> unconditionally and removed the need for this.  Later commit acc8f8628c37
> ("xfs: attach dquot buffer to dquot log item buffer") did the same for
> dquot items but didn't fully clean up the xfs_clear_li_failed side
> for them.  Stop adding the extra pin for dquot items and remove the
> helpers.
> 
> This happens to fix a call to xfs_buf_free with the AIL lock held,
> which would be incorrect for the unlikely case freeing the buffer
> ends up calling vfree.
> 
> Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>

> ---
>  fs/xfs/xfs_dquot.c      |  3 +--
>  fs/xfs/xfs_inode_item.c |  6 ------
>  fs/xfs/xfs_trans_ail.c  |  5 ++---
>  fs/xfs/xfs_trans_priv.h | 28 ----------------------------
>  4 files changed, 3 insertions(+), 39 deletions(-)
> 
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index edbc521870a1..b4e32f0860b7 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -1186,9 +1186,8 @@ xfs_qm_dqflush_done(
>  	if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) &&
>  	    (lip->li_lsn == qlip->qli_flush_lsn ||
>  	     test_bit(XFS_LI_FAILED, &lip->li_flags))) {
> -
>  		spin_lock(&ailp->ail_lock);
> -		xfs_clear_li_failed(lip);
> +		clear_bit(XFS_LI_FAILED, &lip->li_flags);
>  		if (lip->li_lsn == qlip->qli_flush_lsn) {
>  			/* xfs_ail_update_finish() drops the AIL lock */
>  			tail_lsn = xfs_ail_delete_one(ailp, lip);
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index 40fc1bf900af..c6cb0b6b9e46 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -1089,13 +1089,7 @@ xfs_iflush_abort(
>  	 * state. Whilst the inode is in the AIL, it should have a valid buffer
>  	 * pointer for push operations to access - it is only safe to remove the
>  	 * inode from the buffer once it has been removed from the AIL.
> -	 *
> -	 * We also clear the failed bit before removing the item from the AIL
> -	 * as xfs_trans_ail_delete()->xfs_clear_li_failed() will release buffer
> -	 * references the inode item owns and needs to hold until we've fully
> -	 * aborted the inode log item and detached it from the buffer.
>  	 */
> -	clear_bit(XFS_LI_FAILED, &iip->ili_item.li_flags);
>  	xfs_trans_ail_delete(&iip->ili_item, 0);
> 
>  	/*
> diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
> index 0fcb1828e598..85a649fec6ac 100644
> --- a/fs/xfs/xfs_trans_ail.c
> +++ b/fs/xfs/xfs_trans_ail.c
> @@ -909,10 +909,9 @@ xfs_trans_ail_delete(
>  		return;
>  	}
> 
> -	/* xfs_ail_update_finish() drops the AIL lock */
> -	xfs_clear_li_failed(lip);
> +	clear_bit(XFS_LI_FAILED, &lip->li_flags);
>  	tail_lsn = xfs_ail_delete_one(ailp, lip);
> -	xfs_ail_update_finish(ailp, tail_lsn);
> +	xfs_ail_update_finish(ailp, tail_lsn);	/* drops the AIL lock */
>  }
> 
>  int
> diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
> index bd841df93021..f945f0450b16 100644
> --- a/fs/xfs/xfs_trans_priv.h
> +++ b/fs/xfs/xfs_trans_priv.h
> @@ -167,32 +167,4 @@ xfs_trans_ail_copy_lsn(
>  }
>  #endif
> 
> -static inline void
> -xfs_clear_li_failed(
> -	struct xfs_log_item	*lip)
> -{
> -	struct xfs_buf	*bp = lip->li_buf;
> -
> -	ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags));
> -	lockdep_assert_held(&lip->li_ailp->ail_lock);
> -
> -	if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) {
> -		lip->li_buf = NULL;
> -		xfs_buf_rele(bp);
> -	}
> -}
> -
> -static inline void
> -xfs_set_li_failed(
> -	struct xfs_log_item	*lip,
> -	struct xfs_buf		*bp)
> -{
> -	lockdep_assert_held(&lip->li_ailp->ail_lock);
> -
> -	if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) {
> -		xfs_buf_hold(bp);
> -		lip->li_buf = bp;
> -	}
> -}
> -
>  #endif	/* __XFS_TRANS_PRIV_H__ */
> --
> 2.45.2
>
diff mbox series

Patch

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index edbc521870a1..b4e32f0860b7 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -1186,9 +1186,8 @@  xfs_qm_dqflush_done(
 	if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) &&
 	    (lip->li_lsn == qlip->qli_flush_lsn ||
 	     test_bit(XFS_LI_FAILED, &lip->li_flags))) {
-
 		spin_lock(&ailp->ail_lock);
-		xfs_clear_li_failed(lip);
+		clear_bit(XFS_LI_FAILED, &lip->li_flags);
 		if (lip->li_lsn == qlip->qli_flush_lsn) {
 			/* xfs_ail_update_finish() drops the AIL lock */
 			tail_lsn = xfs_ail_delete_one(ailp, lip);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 40fc1bf900af..c6cb0b6b9e46 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -1089,13 +1089,7 @@  xfs_iflush_abort(
 	 * state. Whilst the inode is in the AIL, it should have a valid buffer
 	 * pointer for push operations to access - it is only safe to remove the
 	 * inode from the buffer once it has been removed from the AIL.
-	 *
-	 * We also clear the failed bit before removing the item from the AIL
-	 * as xfs_trans_ail_delete()->xfs_clear_li_failed() will release buffer
-	 * references the inode item owns and needs to hold until we've fully
-	 * aborted the inode log item and detached it from the buffer.
 	 */
-	clear_bit(XFS_LI_FAILED, &iip->ili_item.li_flags);
 	xfs_trans_ail_delete(&iip->ili_item, 0);
 
 	/*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 0fcb1828e598..85a649fec6ac 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -909,10 +909,9 @@  xfs_trans_ail_delete(
 		return;
 	}
 
-	/* xfs_ail_update_finish() drops the AIL lock */
-	xfs_clear_li_failed(lip);
+	clear_bit(XFS_LI_FAILED, &lip->li_flags);
 	tail_lsn = xfs_ail_delete_one(ailp, lip);
-	xfs_ail_update_finish(ailp, tail_lsn);
+	xfs_ail_update_finish(ailp, tail_lsn);	/* drops the AIL lock */
 }
 
 int
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index bd841df93021..f945f0450b16 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -167,32 +167,4 @@  xfs_trans_ail_copy_lsn(
 }
 #endif
 
-static inline void
-xfs_clear_li_failed(
-	struct xfs_log_item	*lip)
-{
-	struct xfs_buf	*bp = lip->li_buf;
-
-	ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags));
-	lockdep_assert_held(&lip->li_ailp->ail_lock);
-
-	if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) {
-		lip->li_buf = NULL;
-		xfs_buf_rele(bp);
-	}
-}
-
-static inline void
-xfs_set_li_failed(
-	struct xfs_log_item	*lip,
-	struct xfs_buf		*bp)
-{
-	lockdep_assert_held(&lip->li_ailp->ail_lock);
-
-	if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) {
-		xfs_buf_hold(bp);
-		lip->li_buf = bp;
-	}
-}
-
 #endif	/* __XFS_TRANS_PRIV_H__ */