From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <david@fromorbit.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 3/6] xfs: merge xfs_buf_find() and xfs_buf_get_map()
Date: Sat, 9 Jul 2022 17:15:01 -0700 [thread overview]
Message-ID: <YsoaBXDZP3GAnSc6@magnolia> (raw)
In-Reply-To: <20220707235259.1097443-4-david@fromorbit.com>
On Fri, Jul 08, 2022 at 09:52:56AM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Now that we factored xfs_buf_find(), we can start separating into
> distinct fast and slow paths from xfs_buf_get_map(). We start by
> moving the lookup map and perag setup to _get_map(), and then move
> all the specifics of the fast path lookup into xfs_buf_lookup()
> and call it directly from _get_map(). We the move all the slow path
> code to xfs_buf_find_insert(), which is now also called directly
> from _get_map(). As such, xfs_buf_find() now goes away.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
Makes sense to /me...
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_buf.c | 207 ++++++++++++++++++++++-------------------------
> 1 file changed, 95 insertions(+), 112 deletions(-)
>
> diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
> index 91dc691f40a8..81ca951b451a 100644
> --- a/fs/xfs/xfs_buf.c
> +++ b/fs/xfs/xfs_buf.c
> @@ -531,18 +531,16 @@ xfs_buf_map_verify(
>
> static int
> xfs_buf_find_lock(
> - struct xfs_buftarg *btp,
> struct xfs_buf *bp,
> xfs_buf_flags_t flags)
> {
> if (!xfs_buf_trylock(bp)) {
> if (flags & XBF_TRYLOCK) {
> - xfs_buf_rele(bp);
> - XFS_STATS_INC(btp->bt_mount, xb_busy_locked);
> + XFS_STATS_INC(bp->b_mount, xb_busy_locked);
> return -EAGAIN;
> }
> xfs_buf_lock(bp);
> - XFS_STATS_INC(btp->bt_mount, xb_get_locked_waited);
> + XFS_STATS_INC(bp->b_mount, xb_get_locked_waited);
> }
>
> /*
> @@ -558,113 +556,97 @@ xfs_buf_find_lock(
> return 0;
> }
>
> -static inline struct xfs_buf *
> +static inline int
> xfs_buf_lookup(
> struct xfs_perag *pag,
> - struct xfs_buf_map *map)
> + struct xfs_buf_map *map,
> + xfs_buf_flags_t flags,
> + struct xfs_buf **bpp)
> {
> struct xfs_buf *bp;
> + int error;
>
> + spin_lock(&pag->pag_buf_lock);
> bp = rhashtable_lookup(&pag->pag_buf_hash, map, xfs_buf_hash_params);
> - if (!bp)
> - return NULL;
> + if (!bp) {
> + spin_unlock(&pag->pag_buf_lock);
> + return -ENOENT;
> + }
> atomic_inc(&bp->b_hold);
> - return bp;
> -}
> + spin_unlock(&pag->pag_buf_lock);
>
> -/*
> - * Insert the new_bp into the hash table. This consumes the perag reference
> - * taken for the lookup.
> - */
> -static int
> -xfs_buf_find_insert(
> - struct xfs_buftarg *btp,
> - struct xfs_perag *pag,
> - struct xfs_buf *new_bp)
> -{
> - /* No match found */
> - if (!new_bp) {
> - xfs_perag_put(pag);
> - XFS_STATS_INC(btp->bt_mount, xb_miss_locked);
> - return -ENOENT;
> + error = xfs_buf_find_lock(bp, flags);
> + if (error) {
> + xfs_buf_rele(bp);
> + return error;
> }
>
> - /* the buffer keeps the perag reference until it is freed */
> - new_bp->b_pag = pag;
> - rhashtable_insert_fast(&pag->pag_buf_hash, &new_bp->b_rhash_head,
> - xfs_buf_hash_params);
> + trace_xfs_buf_find(bp, flags, _RET_IP_);
> + *bpp = bp;
> return 0;
> }
>
> /*
> - * Look up a buffer in the buffer cache and return it referenced and locked
> - * in @found_bp.
> - *
> - * If @new_bp is supplied and we have a lookup miss, insert @new_bp into the
> - * cache.
> - *
> - * If XBF_TRYLOCK is set in @flags, only try to lock the buffer and return
> - * -EAGAIN if we fail to lock it.
> - *
> - * Return values are:
> - * -EFSCORRUPTED if have been supplied with an invalid address
> - * -EAGAIN on trylock failure
> - * -ENOENT if we fail to find a match and @new_bp was NULL
> - * 0, with @found_bp:
> - * - @new_bp if we inserted it into the cache
> - * - the buffer we found and locked.
> + * Insert the new_bp into the hash table. This consumes the perag reference
> + * taken for the lookup regardless of the result of the insert.
> */
> static int
> -xfs_buf_find(
> +xfs_buf_find_insert(
> struct xfs_buftarg *btp,
> + struct xfs_perag *pag,
> + struct xfs_buf_map *cmap,
> struct xfs_buf_map *map,
> int nmaps,
> xfs_buf_flags_t flags,
> - struct xfs_buf *new_bp,
> - struct xfs_buf **found_bp)
> + struct xfs_buf **bpp)
> {
> - struct xfs_perag *pag;
> + struct xfs_buf *new_bp;
> struct xfs_buf *bp;
> - struct xfs_buf_map cmap = { .bm_bn = map[0].bm_bn };
> int error;
> - int i;
> -
> - *found_bp = NULL;
> -
> - for (i = 0; i < nmaps; i++)
> - cmap.bm_len += map[i].bm_len;
>
> - error = xfs_buf_map_verify(btp, &cmap);
> + error = _xfs_buf_alloc(btp, map, nmaps, flags, &new_bp);
> if (error)
> - return error;
> + goto out_drop_pag;
>
> - pag = xfs_perag_get(btp->bt_mount,
> - xfs_daddr_to_agno(btp->bt_mount, cmap.bm_bn));
> + /*
> + * For buffers that fit entirely within a single page, first attempt to
> + * allocate the memory from the heap to minimise memory usage. If we
> + * can't get heap memory for these small buffers, we fall back to using
> + * the page allocator.
> + */
> + if (BBTOB(new_bp->b_length) >= PAGE_SIZE ||
> + xfs_buf_alloc_kmem(new_bp, flags) < 0) {
> + error = xfs_buf_alloc_pages(new_bp, flags);
> + if (error)
> + goto out_free_buf;
> + }
>
> spin_lock(&pag->pag_buf_lock);
> - bp = xfs_buf_lookup(pag, &cmap);
> - if (bp)
> - goto found;
> + bp = rhashtable_lookup(&pag->pag_buf_hash, cmap, xfs_buf_hash_params);
> + if (bp) {
> + atomic_inc(&bp->b_hold);
> + spin_unlock(&pag->pag_buf_lock);
> + error = xfs_buf_find_lock(bp, flags);
> + if (error)
> + xfs_buf_rele(bp);
> + else
> + *bpp = bp;
> + goto out_free_buf;
> + }
>
> - error = xfs_buf_find_insert(btp, pag, new_bp);
> + /* The buffer keeps the perag reference until it is freed. */
> + new_bp->b_pag = pag;
> + rhashtable_insert_fast(&pag->pag_buf_hash, &new_bp->b_rhash_head,
> + xfs_buf_hash_params);
> spin_unlock(&pag->pag_buf_lock);
> - if (error)
> - return error;
> - *found_bp = new_bp;
> + *bpp = new_bp;
> return 0;
>
> -found:
> - spin_unlock(&pag->pag_buf_lock);
> +out_free_buf:
> + xfs_buf_free(new_bp);
> +out_drop_pag:
> xfs_perag_put(pag);
> -
> - error = xfs_buf_find_lock(btp, bp, flags);
> - if (error)
> - return error;
> -
> - trace_xfs_buf_find(bp, flags, _RET_IP_);
> - XFS_STATS_INC(btp->bt_mount, xb_get_locked);
> - *found_bp = bp;
> - return 0;
> + return error;
> }
>
> /*
> @@ -674,54 +656,54 @@ xfs_buf_find(
> */
> int
> xfs_buf_get_map(
> - struct xfs_buftarg *target,
> + struct xfs_buftarg *btp,
> struct xfs_buf_map *map,
> int nmaps,
> xfs_buf_flags_t flags,
> struct xfs_buf **bpp)
> {
> - struct xfs_buf *bp;
> - struct xfs_buf *new_bp;
> + struct xfs_perag *pag;
> + struct xfs_buf *bp = NULL;
> + struct xfs_buf_map cmap = { .bm_bn = map[0].bm_bn };
> int error;
> + int i;
>
> - *bpp = NULL;
> - error = xfs_buf_find(target, map, nmaps, flags, NULL, &bp);
> - if (!error)
> - goto found;
> - if (error != -ENOENT)
> - return error;
> - if (flags & XBF_INCORE)
> - return -ENOENT;
> + for (i = 0; i < nmaps; i++)
> + cmap.bm_len += map[i].bm_len;
>
> - error = _xfs_buf_alloc(target, map, nmaps, flags, &new_bp);
> + error = xfs_buf_map_verify(btp, &cmap);
> if (error)
> return error;
>
> - /*
> - * For buffers that fit entirely within a single page, first attempt to
> - * allocate the memory from the heap to minimise memory usage. If we
> - * can't get heap memory for these small buffers, we fall back to using
> - * the page allocator.
> - */
> - if (BBTOB(new_bp->b_length) >= PAGE_SIZE ||
> - xfs_buf_alloc_kmem(new_bp, flags) < 0) {
> - error = xfs_buf_alloc_pages(new_bp, flags);
> - if (error)
> - goto out_free_buf;
> - }
> + pag = xfs_perag_get(btp->bt_mount,
> + xfs_daddr_to_agno(btp->bt_mount, cmap.bm_bn));
>
> - error = xfs_buf_find(target, map, nmaps, flags, new_bp, &bp);
> - if (error)
> - goto out_free_buf;
> + error = xfs_buf_lookup(pag, &cmap, flags, &bp);
> + if (error && error != -ENOENT)
> + goto out_put_perag;
> +
> + /* cache hits always outnumber misses by at least 10:1 */
> + if (unlikely(!bp)) {
> + XFS_STATS_INC(btp->bt_mount, xb_miss_locked);
>
> - if (bp != new_bp)
> - xfs_buf_free(new_bp);
> + if (flags & XBF_INCORE)
> + goto out_put_perag;
>
> -found:
> + /* xfs_buf_find_insert() consumes the perag reference. */
> + error = xfs_buf_find_insert(btp, pag, &cmap, map, nmaps,
> + flags, &bp);
> + if (error)
> + return error;
> + } else {
> + XFS_STATS_INC(btp->bt_mount, xb_get_locked);
> + xfs_perag_put(pag);
> + }
> +
> + /* We do not hold a perag reference anymore. */
> if (!bp->b_addr) {
> error = _xfs_buf_map_pages(bp, flags);
> if (unlikely(error)) {
> - xfs_warn_ratelimited(target->bt_mount,
> + xfs_warn_ratelimited(btp->bt_mount,
> "%s: failed to map %u pages", __func__,
> bp->b_page_count);
> xfs_buf_relse(bp);
> @@ -736,12 +718,13 @@ xfs_buf_get_map(
> if (!(flags & XBF_READ))
> xfs_buf_ioerror(bp, 0);
>
> - XFS_STATS_INC(target->bt_mount, xb_get);
> + XFS_STATS_INC(btp->bt_mount, xb_get);
> trace_xfs_buf_get(bp, flags, _RET_IP_);
> *bpp = bp;
> return 0;
> -out_free_buf:
> - xfs_buf_free(new_bp);
> +
> +out_put_perag:
> + xfs_perag_put(pag);
> return error;
> }
>
> --
> 2.36.1
>
next prev parent reply other threads:[~2022-07-10 0:15 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-07 23:52 [PATCH 0/6 v3] xfs: lockless buffer lookups Dave Chinner
2022-07-07 23:52 ` [PATCH 1/6] xfs: rework xfs_buf_incore() API Dave Chinner
2022-07-07 23:52 ` [PATCH 2/6] xfs: break up xfs_buf_find() into individual pieces Dave Chinner
2022-07-09 22:58 ` Darrick J. Wong
2022-07-07 23:52 ` [PATCH 3/6] xfs: merge xfs_buf_find() and xfs_buf_get_map() Dave Chinner
2022-07-10 0:15 ` Darrick J. Wong [this message]
2022-07-11 5:14 ` Christoph Hellwig
2022-07-12 0:01 ` Dave Chinner
2022-07-07 23:52 ` [PATCH 4/6] xfs: reduce the number of atomic when locking a buffer after lookup Dave Chinner
2022-07-07 23:52 ` [PATCH 5/6] xfs: remove a superflous hash lookup when inserting new buffers Dave Chinner
2022-07-07 23:52 ` [PATCH 6/6] xfs: lockless buffer lookup Dave Chinner
2022-07-10 0:15 ` Darrick J. Wong
2022-07-13 17:01 ` [PATCH 0/6 v3] xfs: lockless buffer lookups Darrick J. Wong
2022-07-13 17:03 ` Darrick J. Wong
2022-07-14 1:32 ` Dave Chinner
2022-07-14 2:11 ` Darrick J. Wong
-- strict thread matches above, loose matches on Subject: below --
2022-06-27 6:08 [PATCH 0/6 v2] " Dave Chinner
2022-06-27 6:08 ` [PATCH 3/6] xfs: merge xfs_buf_find() and xfs_buf_get_map() Dave Chinner
2022-06-29 7:40 ` Christoph Hellwig
2022-06-29 22:06 ` Darrick J. Wong
2022-07-07 12:39 ` Dave Chinner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YsoaBXDZP3GAnSc6@magnolia \
--to=djwong@kernel.org \
--cc=david@fromorbit.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox