[PATCH 50/50] xfs: use reference counts to free clean buffer items

Mark Tinguely tinguely at sgi.com
Tue Aug 13 10:03:19 CDT 2013


On 08/12/13 05:50, Dave Chinner wrote:
> From: Dave Chinner<dchinner at redhat.com>
>
> When a transaction is cancelled and the buffer log item is clean in
> the transaction, the buffer log item is unconditionally freed. If
> the log item is in the AIL, however, this leads to a use after free
> condition as the item still has other users.
>
> In this case, xfs_buf_item_relse() should only be called on clean
> buffer items if the reference count has dropped to zero. This
> ensures only the last user frees the item.
>
> Signed-off-by: Dave Chinner<dchinner at redhat.com>
> ---
>   fs/xfs/xfs_buf_item.c | 6 ++----
>   1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
> index 9358504..3a944b1 100644
> --- a/fs/xfs/xfs_buf_item.c
> +++ b/fs/xfs/xfs_buf_item.c
> @@ -613,11 +613,9 @@ xfs_buf_item_unlock(
>   			}
>   		}
>   	}
> -	if (clean)
> -		xfs_buf_item_relse(bp);
> -	else if (aborted) {
> +	if (clean || aborted) {
>   		if (atomic_dec_and_test(&bip->bli_refcount)) {
> -			ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
> +			ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp));
>   			xfs_buf_item_relse(bp);
>   		}
>   	} else

why is a clean buffer on the AIL? Racing with a completion handler?

rather than this:

	if (clean || aborted) {
		if (atomic_dec_and_test(&bip->bli_refcount)) {
			ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp));
			xfs_buf_item_relse(bp);
		}
	} else
		atomic_dec(&bip->bli_refcount);

why not fold it into this:

	if (atomic_dec_and_test(&bip->bli_refcount)) {
		ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp));
		xfs_buf_item_relse(bp);
	}

--Mark.



More information about the xfs mailing list