Re: [PATCH 17/18] xfs: add a lru to the XFS buffer cache

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

 



On Tue, 2010-09-14 at 20:56 +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> Introduce a per-buftarg LRU for memory reclaim to operate on. This
> is the last piece we need to put in place so that we can fully
> control the buffer lifecycle. This allows XFS to be responsibile for
> maintaining the working set of buffers under memory pressure instead
> of relying on the VM reclaim not to take pages we need out from
> underneath us.
> 
> The implementation is currently a bit naive - it does not rotate
> buffers on the LRU when they are accessed multiple times. Solving
> this problem is for a later patch series that re-introduces the
> buffer type specific reclaim reference counts to prioritise reclaim
> more effectively.

Two small comments below, otherwise looks good.

Reviewed-by: Alex Elder <aelder@xxxxxxx>

> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> ---
>  fs/xfs/linux-2.6/xfs_buf.c |   91 ++++++++++++++++++++++++++++++++++---------
>  fs/xfs/linux-2.6/xfs_buf.h |    5 ++
>  2 files changed, 77 insertions(+), 19 deletions(-)
> 
> diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
> index 3b54fee..12b37c6 100644
> --- a/fs/xfs/linux-2.6/xfs_buf.c
> +++ b/fs/xfs/linux-2.6/xfs_buf.c

. . .

> @@ -1446,27 +1466,29 @@ xfs_buf_iomove(
>   */
>  
>  /*
> - *	Wait for any bufs with callbacks that have been submitted but
> - *	have not yet returned... walk the hash list for the target.
> + * Wait for any bufs with callbacks that have been submitted but have not yet
> + * returned. These buffers will have an elevated hold count, so wait on those
> + * while freeing all the buffers only held by the LRU.
>   */
>  void
>  xfs_wait_buftarg(
>  	struct xfs_buftarg	*btp)
>  {
> -	struct xfs_perag	*pag;
> -	uint			i;
> -
> -	for (i = 0; i < btp->bt_mount->m_sb.sb_agcount; i++) {
> -		pag = xfs_perag_get(btp->bt_mount, i);
> -		spin_lock(&pag->pag_buf_lock);
> -		while (rb_first(&pag->pag_buf_tree)) {
> -			spin_unlock(&pag->pag_buf_lock);
> +	struct xfs_buf		*bp;

(Insert blank line here.)

> +restart:
> +	spin_lock(&btp->bt_lru_lock);
> +	while (!list_empty(&btp->bt_lru)) {
> +		bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
> +		if (atomic_read(&bp->b_hold) > 1) {
> +			spin_unlock(&btp->bt_lru_lock);
>  			delay(100);
> -			spin_lock(&pag->pag_buf_lock);
> +			goto restart;
>  		}
> -		spin_unlock(&pag->pag_buf_lock);
> -		xfs_perag_put(pag);
> +		spin_unlock(&btp->bt_lru_lock);
> +		xfs_buf_rele(bp);
> +		spin_lock(&btp->bt_lru_lock);
>  	}
> +	spin_unlock(&btp->bt_lru_lock);
>  }
>  
>  int
> @@ -1477,15 +1499,44 @@ xfs_buftarg_shrink(
>  {
>  	struct xfs_buftarg	*btp = container_of(shrink,
>  					struct xfs_buftarg, bt_shrinker);
> -	if (nr_to_scan) {
> -		if (test_bit(XBT_FORCE_SLEEP, &btp->bt_flags))
> -			return -1;
> -		if (list_empty(&btp->bt_delwrite_queue))
> -			return -1;
> +	struct xfs_buf		*bp, *n;
> +
> +	if (!nr_to_scan)
> +		return btp->bt_lru_nr;
> +
> +	spin_lock(&btp->bt_lru_lock);
> +	if (test_and_set_bit(XBT_SHRINKER_ACTIVE, &btp->bt_flags)) {

Since test_and_set_bit() and clear_bit() are already atomic
you don't need to be under protection of bt_lru_lock to
manipulate the flags.  Get the spinlock after you've set
XBT_SHRINKER_ACTIVE (and clear it outside the spinlock
also).

> +		/* LRU walk already in progress */
> +		spin_unlock(&btp->bt_lru_lock);
> +		return -1;
> +	}
> +
> +	list_for_each_entry_safe(bp, n, &btp->bt_lru, b_lru) {
> +		if (nr_to_scan-- <= 0)
> +			break;

. . .

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs


[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux