From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <david@fromorbit.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 28/39] xfs: rework per-iclog header CIL reservation
Date: Thu, 27 May 2021 11:17:55 -0700 [thread overview]
Message-ID: <20210527181755.GG2402049@locust> (raw)
In-Reply-To: <20210519121317.585244-29-david@fromorbit.com>
On Wed, May 19, 2021 at 10:13:06PM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> For every iclog that a CIL push will use up, we need to ensure we
> have space reserved for the iclog header in each iclog. It is
> extremely difficult to do this accurately with a per-cpu counter
> without expensive summing of the counter in every commit. However,
> we know what the maximum CIL size is going to be because of the
> hard space limit we have, and hence we know exactly how many iclogs
> we are going to need to write out the CIL.
>
> We are constrained by the requirement that small transactions only
> have reservation space for a single iclog header built into them.
> At commit time we don't know how much of the current transaction
> reservation is made up of iclog header reservations as calculated by
> xfs_log_calc_unit_res() when the ticket was reserved. As larger
> reservations have multiple header spaces reserved, we can steal
> more than one iclog header reservation at a time, but we only steal
> the exact number needed for the given log vector size delta.
>
> As a result, we don't know exactly when we are going to steal iclog
> header reservations, nor do we know exactly how many we are going to
> need for a given CIL.
>
> To make things simple, start by calculating the worst case number of
> iclog headers a full CIL push will require. Record this into an
> atomic variable in the CIL. Then add a byte counter to the log
> ticket that records exactly how much iclog header space has been
> reserved in this ticket by xfs_log_calc_unit_res(). This tells us
> exactly how much space we can steal from the ticket at transaction
> commit time.
>
> Now, at transaction commit time, we can check if the CIL has a full
> iclog header reservation and, if not, steal the entire reservation
> the current ticket holds for iclog headers. This minimises the
> number of times we need to do atomic operations in the fast path,
> but still guarantees we get all the reservations we need.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
No new questions since last time, so:
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_log.c | 9 ++++---
> fs/xfs/xfs_log_cil.c | 55 +++++++++++++++++++++++++++++++++----------
> fs/xfs/xfs_log_priv.h | 20 +++++++++-------
> 3 files changed, 59 insertions(+), 25 deletions(-)
>
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index 65b28fce4db4..77d9ea7daf26 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -3307,7 +3307,8 @@ xfs_log_ticket_get(
> static int
> xlog_calc_unit_res(
> struct xlog *log,
> - int unit_bytes)
> + int unit_bytes,
> + int *niclogs)
> {
> int iclog_space;
> uint num_headers;
> @@ -3387,6 +3388,8 @@ xlog_calc_unit_res(
> /* roundoff padding for transaction data and one for commit record */
> unit_bytes += 2 * log->l_iclog_roundoff;
>
> + if (niclogs)
> + *niclogs = num_headers;
> return unit_bytes;
> }
>
> @@ -3395,7 +3398,7 @@ xfs_log_calc_unit_res(
> struct xfs_mount *mp,
> int unit_bytes)
> {
> - return xlog_calc_unit_res(mp->m_log, unit_bytes);
> + return xlog_calc_unit_res(mp->m_log, unit_bytes, NULL);
> }
>
> /*
> @@ -3413,7 +3416,7 @@ xlog_ticket_alloc(
>
> tic = kmem_cache_zalloc(xfs_log_ticket_zone, GFP_NOFS | __GFP_NOFAIL);
>
> - unit_res = xlog_calc_unit_res(log, unit_bytes);
> + unit_res = xlog_calc_unit_res(log, unit_bytes, &tic->t_iclog_hdrs);
>
> atomic_set(&tic->t_ref, 1);
> tic->t_task = current;
> diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
> index 4637f8711ada..87d4eb321fdc 100644
> --- a/fs/xfs/xfs_log_cil.c
> +++ b/fs/xfs/xfs_log_cil.c
> @@ -44,9 +44,20 @@ xlog_cil_ticket_alloc(
> * transaction overhead reservation from the first transaction commit.
> */
> tic->t_curr_res = 0;
> + tic->t_iclog_hdrs = 0;
> return tic;
> }
>
> +static inline void
> +xlog_cil_set_iclog_hdr_count(struct xfs_cil *cil)
> +{
> + struct xlog *log = cil->xc_log;
> +
> + atomic_set(&cil->xc_iclog_hdrs,
> + (XLOG_CIL_BLOCKING_SPACE_LIMIT(log) /
> + (log->l_iclog_size - log->l_iclog_hsize)));
> +}
> +
> /*
> * Unavoidable forward declaration - xlog_cil_push_work() calls
> * xlog_cil_ctx_alloc() itself.
> @@ -70,6 +81,7 @@ xlog_cil_ctx_switch(
> struct xfs_cil *cil,
> struct xfs_cil_ctx *ctx)
> {
> + xlog_cil_set_iclog_hdr_count(cil);
> set_bit(XLOG_CIL_EMPTY, &cil->xc_flags);
> ctx->sequence = ++cil->xc_current_sequence;
> ctx->cil = cil;
> @@ -92,6 +104,7 @@ xlog_cil_init_post_recovery(
> {
> log->l_cilp->xc_ctx->ticket = xlog_cil_ticket_alloc(log);
> log->l_cilp->xc_ctx->sequence = 1;
> + xlog_cil_set_iclog_hdr_count(log->l_cilp);
> }
>
> static inline int
> @@ -419,7 +432,6 @@ xlog_cil_insert_items(
> struct xfs_cil_ctx *ctx = cil->xc_ctx;
> struct xfs_log_item *lip;
> int len = 0;
> - int iclog_space;
> int iovhdr_res = 0, split_res = 0, ctx_res = 0;
>
> ASSERT(tp);
> @@ -442,19 +454,36 @@ xlog_cil_insert_items(
> test_and_clear_bit(XLOG_CIL_EMPTY, &cil->xc_flags))
> ctx_res = ctx->ticket->t_unit_res;
>
> - spin_lock(&cil->xc_cil_lock);
> -
> - /* do we need space for more log record headers? */
> - iclog_space = log->l_iclog_size - log->l_iclog_hsize;
> - if (len > 0 && (ctx->space_used / iclog_space !=
> - (ctx->space_used + len) / iclog_space)) {
> - split_res = (len + iclog_space - 1) / iclog_space;
> - /* need to take into account split region headers, too */
> - split_res *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
> - ctx->ticket->t_unit_res += split_res;
> + /*
> + * Check if we need to steal iclog headers. atomic_read() is not a
> + * locked atomic operation, so we can check the value before we do any
> + * real atomic ops in the fast path. If we've already taken the CIL unit
> + * reservation from this commit, we've already got one iclog header
> + * space reserved so we have to account for that otherwise we risk
> + * overrunning the reservation on this ticket.
> + *
> + * If the CIL is already at the hard limit, we might need more header
> + * space that originally reserved. So steal more header space from every
> + * commit that occurs once we are over the hard limit to ensure the CIL
> + * push won't run out of reservation space.
> + *
> + * This can steal more than we need, but that's OK.
> + */
> + if (atomic_read(&cil->xc_iclog_hdrs) > 0 ||
> + ctx->space_used + len >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log)) {
> + int split_res = log->l_iclog_hsize +
> + sizeof(struct xlog_op_header);
> + if (ctx_res)
> + ctx_res += split_res * (tp->t_ticket->t_iclog_hdrs - 1);
> + else
> + ctx_res = split_res * tp->t_ticket->t_iclog_hdrs;
> + atomic_sub(tp->t_ticket->t_iclog_hdrs, &cil->xc_iclog_hdrs);
> }
> - tp->t_ticket->t_curr_res -= split_res + ctx_res + len;
> - ctx->ticket->t_curr_res += split_res + ctx_res;
> +
> + spin_lock(&cil->xc_cil_lock);
> + tp->t_ticket->t_curr_res -= ctx_res + len;
> + ctx->ticket->t_unit_res += ctx_res;
> + ctx->ticket->t_curr_res += ctx_res;
> ctx->space_used += len;
>
> /*
> diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
> index 11606c378b7f..85a85ab569fe 100644
> --- a/fs/xfs/xfs_log_priv.h
> +++ b/fs/xfs/xfs_log_priv.h
> @@ -137,15 +137,16 @@ enum xlog_iclog_state {
> #define XLOG_ICL_NEED_FUA (1 << 1) /* iclog needs REQ_FUA */
>
> typedef struct xlog_ticket {
> - struct list_head t_queue; /* reserve/write queue */
> - struct task_struct *t_task; /* task that owns this ticket */
> - xlog_tid_t t_tid; /* transaction identifier : 4 */
> - atomic_t t_ref; /* ticket reference count : 4 */
> - int t_curr_res; /* current reservation in bytes : 4 */
> - int t_unit_res; /* unit reservation in bytes : 4 */
> - char t_ocnt; /* original count : 1 */
> - char t_cnt; /* current count : 1 */
> - char t_flags; /* properties of reservation : 1 */
> + struct list_head t_queue; /* reserve/write queue */
> + struct task_struct *t_task; /* task that owns this ticket */
> + xlog_tid_t t_tid; /* transaction identifier */
> + atomic_t t_ref; /* ticket reference count */
> + int t_curr_res; /* current reservation */
> + int t_unit_res; /* unit reservation */
> + char t_ocnt; /* original count */
> + char t_cnt; /* current count */
> + char t_flags; /* properties of reservation */
> + int t_iclog_hdrs; /* iclog hdrs in t_curr_res */
> } xlog_ticket_t;
>
> /*
> @@ -245,6 +246,7 @@ struct xfs_cil_ctx {
> struct xfs_cil {
> struct xlog *xc_log;
> unsigned long xc_flags;
> + atomic_t xc_iclog_hdrs;
> struct list_head xc_cil;
> spinlock_t xc_cil_lock;
>
> --
> 2.31.1
>
next prev parent reply other threads:[~2021-05-27 18:17 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-19 12:12 [PATCH 00/39 v4] xfs: CIL and log optimisations Dave Chinner
2021-05-19 12:12 ` [PATCH 01/39] xfs: log stripe roundoff is a property of the log Dave Chinner
2021-05-28 0:54 ` Allison Henderson
2021-05-19 12:12 ` [PATCH 02/39] xfs: separate CIL commit record IO Dave Chinner
2021-05-28 0:54 ` Allison Henderson
2021-05-19 12:12 ` [PATCH 03/39] xfs: remove xfs_blkdev_issue_flush Dave Chinner
2021-05-28 0:54 ` Allison Henderson
2021-05-19 12:12 ` [PATCH 04/39] xfs: async blkdev cache flush Dave Chinner
2021-05-20 23:53 ` Darrick J. Wong
2021-05-28 0:54 ` Allison Henderson
2021-05-19 12:12 ` [PATCH 05/39] xfs: CIL checkpoint flushes caches unconditionally Dave Chinner
2021-05-28 0:54 ` Allison Henderson
2021-05-19 12:12 ` [PATCH 06/39] xfs: remove need_start_rec parameter from xlog_write() Dave Chinner
2021-05-19 12:12 ` [PATCH 07/39] xfs: journal IO cache flush reductions Dave Chinner
2021-05-21 0:16 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 08/39] xfs: Fix CIL throttle hang when CIL space used going backwards Dave Chinner
2021-05-19 12:12 ` [PATCH 09/39] xfs: xfs_log_force_lsn isn't passed a LSN Dave Chinner
2021-05-21 0:20 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 10/39] xfs: AIL needs asynchronous CIL forcing Dave Chinner
2021-05-21 0:33 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 11/39] xfs: CIL work is serialised, not pipelined Dave Chinner
2021-05-21 0:32 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 12/39] xfs: factor out the CIL transaction header building Dave Chinner
2021-05-19 12:12 ` [PATCH 13/39] xfs: only CIL pushes require a start record Dave Chinner
2021-05-19 12:12 ` [PATCH 14/39] xfs: embed the xlog_op_header in the unmount record Dave Chinner
2021-05-21 0:35 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 15/39] xfs: embed the xlog_op_header in the commit record Dave Chinner
2021-05-19 12:12 ` [PATCH 16/39] xfs: log tickets don't need log client id Dave Chinner
2021-05-21 0:38 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 17/39] xfs: move log iovec alignment to preparation function Dave Chinner
2021-05-19 12:12 ` [PATCH 18/39] xfs: reserve space and initialise xlog_op_header in item formatting Dave Chinner
2021-05-19 12:12 ` [PATCH 19/39] xfs: log ticket region debug is largely useless Dave Chinner
2021-05-19 12:12 ` [PATCH 20/39] xfs: pass lv chain length into xlog_write() Dave Chinner
2021-05-27 17:20 ` Darrick J. Wong
2021-06-02 22:18 ` Dave Chinner
2021-06-02 22:24 ` Darrick J. Wong
2021-06-02 22:58 ` [PATCH 20/39 V2] " Dave Chinner
2021-06-02 23:01 ` Darrick J. Wong
2021-05-19 12:12 ` [PATCH 21/39] xfs: introduce xlog_write_single() Dave Chinner
2021-05-27 17:27 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 22/39] xfs:_introduce xlog_write_partial() Dave Chinner
2021-05-27 18:06 ` Darrick J. Wong
2021-06-02 22:21 ` Dave Chinner
2021-05-19 12:13 ` [PATCH 23/39] xfs: xlog_write() no longer needs contwr state Dave Chinner
2021-05-19 12:13 ` [PATCH 24/39] xfs: xlog_write() doesn't need optype anymore Dave Chinner
2021-05-27 18:07 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 25/39] xfs: CIL context doesn't need to count iovecs Dave Chinner
2021-05-27 18:08 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 26/39] xfs: use the CIL space used counter for emptiness checks Dave Chinner
2021-05-19 12:13 ` [PATCH 27/39] xfs: lift init CIL reservation out of xc_cil_lock Dave Chinner
2021-05-19 12:13 ` [PATCH 28/39] xfs: rework per-iclog header CIL reservation Dave Chinner
2021-05-27 18:17 ` Darrick J. Wong [this message]
2021-05-19 12:13 ` [PATCH 29/39] xfs: introduce per-cpu CIL tracking structure Dave Chinner
2021-05-27 18:31 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 30/39] xfs: implement percpu cil space used calculation Dave Chinner
2021-05-27 18:41 ` Darrick J. Wong
2021-06-02 23:47 ` Dave Chinner
2021-06-03 1:26 ` Darrick J. Wong
2021-06-03 2:28 ` Dave Chinner
2021-06-03 3:01 ` Darrick J. Wong
2021-06-03 3:56 ` Dave Chinner
2021-05-19 12:13 ` [PATCH 31/39] xfs: track CIL ticket reservation in percpu structure Dave Chinner
2021-05-27 18:48 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 32/39] xfs: convert CIL busy extents to per-cpu Dave Chinner
2021-05-27 18:49 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 33/39] xfs: Add order IDs to log items in CIL Dave Chinner
2021-05-27 19:00 ` Darrick J. Wong
2021-06-03 0:16 ` Dave Chinner
2021-06-03 0:49 ` Darrick J. Wong
2021-06-03 2:13 ` Dave Chinner
2021-06-03 3:02 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 34/39] xfs: convert CIL to unordered per cpu lists Dave Chinner
2021-05-27 19:03 ` Darrick J. Wong
2021-06-03 0:27 ` Dave Chinner
2021-05-19 12:13 ` [PATCH 35/39] xfs: convert log vector chain to use list heads Dave Chinner
2021-05-27 19:13 ` Darrick J. Wong
2021-06-03 0:38 ` Dave Chinner
2021-06-03 0:50 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 36/39] xfs: move CIL ordering to the logvec chain Dave Chinner
2021-05-27 19:14 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 37/39] xfs: avoid cil push lock if possible Dave Chinner
2021-05-27 19:18 ` Darrick J. Wong
2021-05-19 12:13 ` [PATCH 38/39] xfs: xlog_sync() manually adjusts grant head space Dave Chinner
2021-05-19 12:13 ` [PATCH 39/39] xfs: expanding delayed logging design with background material Dave Chinner
2021-05-27 20:38 ` Darrick J. Wong
2021-06-03 0:57 ` Dave Chinner
2021-06-03 5:22 [PATCH 00/39 v5] xfs: CIL and log optimisations Dave Chinner
2021-06-03 5:22 ` [PATCH 28/39] xfs: rework per-iclog header CIL reservation 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=20210527181755.GG2402049@locust \
--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;
as well as URLs for NNTP newsgroup(s).