Re: [PATCH v3 1/2] xfs: fix up quotacheck buffer list error handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 21, 2017 at 08:22:12AM -0400, Brian Foster wrote:
> The quotacheck error handling of the delwri buffer list assumes the
> resident buffers are locked and doesn't clear the _XBF_DELWRI_Q flag
> on the buffers that are dequeued. This can lead to assert failures
> on buffer release and possibly other locking problems.
> 
> Move this code to a delwri queue cancel helper function to
> encapsulate the logic required to properly release buffers from a
> delwri queue. Update the helper to clear the delwri queue flag and
> call it from quotacheck.
> 
> Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>

I /think/ this one is ok -- it's useful to assert that the buffer is
actually locked before we try to unlock it, and the other parts refactor
existing code.

If we want to be super-pedantic, then yes, delwri_submit consumes the
entire list and we don't need to touch buffer_list if we hit the final
"goto error_return;" in quotacheck.  OTOH I feel like there's not much
harm in the extra list_empty check and should we ever decide that
delwri_submit shouldn't consume the whole list, then we're already
covered.

Regardless, if anyone /does/ want that change, it can be a separate
patch.

Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>

--D

> ---
>  fs/xfs/xfs_buf.c | 24 ++++++++++++++++++++++++
>  fs/xfs/xfs_buf.h |  1 +
>  fs/xfs/xfs_qm.c  |  7 +------
>  3 files changed, 26 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
> index b620872..ba036c1 100644
> --- a/fs/xfs/xfs_buf.c
> +++ b/fs/xfs/xfs_buf.c
> @@ -1079,6 +1079,8 @@ void
>  xfs_buf_unlock(
>  	struct xfs_buf		*bp)
>  {
> +	ASSERT(xfs_buf_islocked(bp));
> +
>  	XB_CLEAR_OWNER(bp);
>  	up(&bp->b_sema);
>  
> @@ -1815,6 +1817,28 @@ xfs_alloc_buftarg(
>  }
>  
>  /*
> + * Cancel a delayed write list.
> + *
> + * Remove each buffer from the list, clear the delwri queue flag and drop the
> + * associated buffer reference.
> + */
> +void
> +xfs_buf_delwri_cancel(
> +	struct list_head	*list)
> +{
> +	struct xfs_buf		*bp;
> +
> +	while (!list_empty(list)) {
> +		bp = list_first_entry(list, struct xfs_buf, b_list);
> +
> +		xfs_buf_lock(bp);
> +		bp->b_flags &= ~_XBF_DELWRI_Q;
> +		list_del_init(&bp->b_list);
> +		xfs_buf_relse(bp);
> +	}
> +}
> +
> +/*
>   * Add a buffer to the delayed write list.
>   *
>   * This queues a buffer for writeout if it hasn't already been.  Note that
> diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
> index e1bc1af..8d1d44f 100644
> --- a/fs/xfs/xfs_buf.h
> +++ b/fs/xfs/xfs_buf.h
> @@ -329,6 +329,7 @@ extern void *xfs_buf_offset(struct xfs_buf *, size_t);
>  extern void xfs_buf_stale(struct xfs_buf *bp);
>  
>  /* Delayed Write Buffer Routines */
> +extern void xfs_buf_delwri_cancel(struct list_head *);
>  extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
>  extern int xfs_buf_delwri_submit(struct list_head *);
>  extern int xfs_buf_delwri_submit_nowait(struct list_head *);
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index b669b12..8b9a9f1 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -1384,12 +1384,7 @@ xfs_qm_quotacheck(
>  	mp->m_qflags |= flags;
>  
>   error_return:
> -	while (!list_empty(&buffer_list)) {
> -		struct xfs_buf *bp =
> -			list_first_entry(&buffer_list, struct xfs_buf, b_list);
> -		list_del_init(&bp->b_list);
> -		xfs_buf_relse(bp);
> -	}
> +	xfs_buf_delwri_cancel(&buffer_list);
>  
>  	if (error) {
>  		xfs_warn(mp,
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux