From: Alex Elder <aelder@sgi.com>
To: Dave Chinner <david@fromorbit.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH 1/4] xfs: use a cursor for bulk AIL insertion
Date: Tue, 19 Jul 2011 18:03:44 -0500 [thread overview]
Message-ID: <1311116624.1964.38.camel@doink> (raw)
In-Reply-To: <1310960419-9875-2-git-send-email-david@fromorbit.com>
On Mon, 2011-07-18 at 13:40 +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Delayed logging can insert tens of thousands of log items into the
> AIL at the same LSN. When the committing of log commit records
> occur, we can get insertions occurring at an LSN that is not at the
> end of the AIL. If there are thousands of items in the AIL on the
> tail LSN, each insertion has to walk the AIL to find the correct
> place to insert the new item into the AIL. This can consume large
> amounts of CPU time and block other operations from occurring while
> the traversals are in progress.
>
> To avoid this repeated walk, use a AIL cursor to record
> where we should be inserting the new items into the AIL without
> having to repeat the walk. The cursor infrastructure already
> provides this functionality for push walks, so is a simple extension
> of existing code. While this will not avoid the initial walk, it
> will avoid repeating it tens of thousands of times during a single
> checkpoint commit.
>
> This version includes logic improvements from Christoph Hellwig.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
I think there's a case that can be improved (though
it isn't wrong as-is), and assuming I'm right, I have
provided a modified splice function (not tested), below.
But if you don't want to change anything, this code
looks OK to me, so:
Reviewed-by: Alex Elder <aelder@sgi.com>
. . .
> +
> +/*
> + * splice the log item list into the AIL at the given LSN. We splice to the
> + * tail of the given LSN to maintain insert order for push traversals. The
> + * cursor is optional, allowing repeated updates to the same LSN to avoid
> + * repeated traversals.
> */
> static void
> xfs_ail_splice(
> - struct xfs_ail *ailp,
> - struct list_head *list,
> - xfs_lsn_t lsn)
> + struct xfs_ail *ailp,
> + struct xfs_ail_cursor *cur,
> + struct list_head *list,
> + xfs_lsn_t lsn)
> {
> - xfs_log_item_t *next_lip;
> + struct xfs_log_item *lip = cur ? cur->item : NULL;
> + struct xfs_log_item *next_lip;
>
> - /* If the list is empty, just insert the item. */
> - if (list_empty(&ailp->xa_ail)) {
> - list_splice(list, &ailp->xa_ail);
> - return;
> + /*
> + * Get a new cursor if we don't have a placeholder or the existing one
> + * has been invalidated.
> + */
> + if (!lip || (__psint_t)lip & 1) {
> + lip = __xfs_trans_ail_cursor_last(ailp, lsn);
> +
> + if (!lip) {
> + /* The list is empty, so just splice and return. */
> + if (cur)
> + cur->item = NULL;
If the AIL was empty, I think we still want to
make the cursor point to the end of the list that's
being spliced in, don't we?
> + list_splice(list, &ailp->xa_ail);
> + return;
> + }
> }
>
> - list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
> - if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)
> - break;
> + /*
> + * Our cursor points to the item we want to insert _after_, so we have
> + * to update the cursor to point to the end of the list we are splicing
> + * in so that it points to the correct location for the next splice.
> + * i.e. before the splice
> + *
> + * lsn -> lsn -> lsn + x -> lsn + x ...
> + * ^
> + * | cursor points here
> + *
> + * After the splice we have:
> + *
> + * lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ...
> + * ^ ^
> + * | cursor points here | needs to move here
> + *
> + * So we set the cursor to the last item in the list to be spliced
> + * before we execute the splice, resulting in the cursor pointing to
> + * the correct item after the splice occurs.
> + */
> + if (cur) {
> + next_lip = list_entry(list->prev, struct xfs_log_item, li_ail);
> + cur->item = next_lip;
> }
> -
> - ASSERT(&next_lip->li_ail == &ailp->xa_ail ||
> - XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0);
> -
> - list_splice_init(list, &next_lip->li_ail);
> + list_splice(list, &lip->li_ail);
> }
>
> /*
So assuming my comment above is right, how about this:
static void
xfs_ail_splice(
struct xfs_ail *ailp,
struct xfs_ail_cursor *cur,
struct list_head *list,
xfs_lsn_t lsn)
{
struct xfs_log_item *lip;
/*
* Use the cursor to determine the insertion point if one is
* provided.
*/
lip = cur ? cur->item : NULL;
if (!lip || (__psint_t) lip & 1)
lip = __xfs_trans_ail_cursor_last(ailp, lsn);
/*
* If a cursor is provided, we know we're processing the AIL
* in lsn order, and future items to be spliced in will
* follow the last one being inserted now. Update the
* cursor to point to that last item, now while we have a
* reliable pointer to it.
*/
if (cur)
cur->item = list_entry(list->prev, struct xfs_log_item,
li_ail);
/*
* Finally perform the splice. Unless the AIL was empty,
* lip points to the item in the AIL _after_ which the new
* items should go. If lip is null the AIL was empty, so
* the new items go at the head of the AIL.
*/
if (lip)
list_splice(list, &lip->li_ail);
else
list_splice(list, &ailp->xa_ail);
}
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2011-07-19 23:03 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1310960419-9875-1-git-send-email-david@fromorbit.com>
2011-07-18 3:40 ` [PATCH 1/4] xfs: use a cursor for bulk AIL insertion Dave Chinner
2011-07-19 2:01 ` Christoph Hellwig
2011-07-19 3:12 ` Dave Chinner
2011-07-19 23:03 ` Alex Elder [this message]
2011-07-19 23:36 ` Dave Chinner
2011-07-20 0:15 ` Christoph Hellwig
2011-07-20 0:21 ` Dave Chinner
2011-07-20 15:13 ` Alex Elder
2011-07-20 15:16 ` Alex Elder
2011-07-18 3:40 ` [PATCH 2/4] xfs: remove confusing ail cursor wrapper Dave Chinner
2011-07-19 23:03 ` Alex Elder
2011-07-18 3:40 ` [PATCH 3/4] xfs: convert AIL cursors to use struct list_head Dave Chinner
2011-07-19 23:03 ` Alex Elder
2011-07-19 23:43 ` Dave Chinner
2011-07-20 15:19 ` Alex Elder
2011-07-18 3:40 ` [PATCH 4/4] xfs: add size update tracepoint to IO completion 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=1311116624.1964.38.camel@doink \
--to=aelder@sgi.com \
--cc=david@fromorbit.com \
--cc=xfs@oss.sgi.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.