From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <david@fromorbit.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 22/39] xfs:_introduce xlog_write_partial()
Date: Thu, 27 May 2021 11:06:59 -0700 [thread overview]
Message-ID: <20210527180659.GD2402049@locust> (raw)
In-Reply-To: <20210519121317.585244-23-david@fromorbit.com>
On Wed, May 19, 2021 at 10:13:00PM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Handle writing of a logvec chain into an iclog that doesn't have
> enough space to fit it all. The iclog has already been changed to
> WANT_SYNC by xlog_get_iclog_space(), so the entire remaining space
> in the iclog is exclusively owned by this logvec chain.
>
> The difference between the single and partial cases is that
> we end up with partial iovec writes in the iclog and have to split
> a log vec regions across two iclogs. The state handling for this is
> currently awful and so we're building up the pieces needed to
> handle this more cleanly one at a time.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
Egad this diff is hard to read. Brian's right, the patience diff is
easier to understand and shorter to boot.
That said, I actually understand what the new code does now, so:
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Might be nice to hoist:
memcpy(ptr, reg->i_addr + reg_offset, rlen);
xlog_write_adv_cnt(&ptr, len, log_offset, rlen);
(*record_cnt)++;
*data_cnt += rlen;
into a helper but it's only four lines so I'm not gonna fuss any
further.
--D
> ---
> fs/xfs/xfs_log.c | 504 ++++++++++++++++++++++-------------------------
> 1 file changed, 240 insertions(+), 264 deletions(-)
>
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index 3b74d21e3786..98a3e2e4f1e0 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -2110,166 +2110,250 @@ xlog_print_trans(
> }
> }
>
> -static xlog_op_header_t *
> -xlog_write_setup_ophdr(
> - struct xlog_op_header *ophdr,
> - struct xlog_ticket *ticket)
> -{
> - ophdr->oh_clientid = XFS_TRANSACTION;
> - ophdr->oh_res2 = 0;
> - ophdr->oh_flags = 0;
> - return ophdr;
> -}
> -
> /*
> - * Set up the parameters of the region copy into the log. This has
> - * to handle region write split across multiple log buffers - this
> - * state is kept external to this function so that this code can
> - * be written in an obvious, self documenting manner.
> + * Write whole log vectors into a single iclog which is guaranteed to have
> + * either sufficient space for the entire log vector chain to be written or
> + * exclusive access to the remaining space in the iclog.
> + *
> + * Return the number of iovecs and data written into the iclog, as well as
> + * a pointer to the logvec that doesn't fit in the log (or NULL if we hit the
> + * end of the chain.
> */
> -static int
> -xlog_write_setup_copy(
> +static struct xfs_log_vec *
> +xlog_write_single(
> + struct xfs_log_vec *log_vector,
> struct xlog_ticket *ticket,
> - struct xlog_op_header *ophdr,
> - int space_available,
> - int space_required,
> - int *copy_off,
> - int *copy_len,
> - int *last_was_partial_copy,
> - int *bytes_consumed)
> -{
> - int still_to_copy;
> -
> - still_to_copy = space_required - *bytes_consumed;
> - *copy_off = *bytes_consumed;
> -
> - if (still_to_copy <= space_available) {
> - /* write of region completes here */
> - *copy_len = still_to_copy;
> - ophdr->oh_len = cpu_to_be32(*copy_len);
> - if (*last_was_partial_copy)
> - ophdr->oh_flags |= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS);
> - *last_was_partial_copy = 0;
> - *bytes_consumed = 0;
> - return 0;
> - }
> -
> - /* partial write of region, needs extra log op header reservation */
> - *copy_len = space_available;
> - ophdr->oh_len = cpu_to_be32(*copy_len);
> - ophdr->oh_flags |= XLOG_CONTINUE_TRANS;
> - if (*last_was_partial_copy)
> - ophdr->oh_flags |= XLOG_WAS_CONT_TRANS;
> - *bytes_consumed += *copy_len;
> - (*last_was_partial_copy)++;
> -
> - /* account for new log op header */
> - ticket->t_curr_res -= sizeof(struct xlog_op_header);
> -
> - return sizeof(struct xlog_op_header);
> -}
> -
> -static int
> -xlog_write_copy_finish(
> - struct xlog *log,
> struct xlog_in_core *iclog,
> - uint flags,
> - int *record_cnt,
> - int *data_cnt,
> - int *partial_copy,
> - int *partial_copy_len,
> - int log_offset,
> - struct xlog_in_core **commit_iclog)
> + uint32_t *log_offset,
> + uint32_t *len,
> + uint32_t *record_cnt,
> + uint32_t *data_cnt)
> {
> - int error;
> + struct xfs_log_vec *lv;
> + void *ptr;
> + int index;
> +
> + ASSERT(*log_offset + *len <= iclog->ic_size ||
> + iclog->ic_state == XLOG_STATE_WANT_SYNC);
>
> - if (*partial_copy) {
> + ptr = iclog->ic_datap + *log_offset;
> + for (lv = log_vector; lv; lv = lv->lv_next) {
> /*
> - * This iclog has already been marked WANT_SYNC by
> - * xlog_state_get_iclog_space.
> + * If the entire log vec does not fit in the iclog, punt it to
> + * the partial copy loop which can handle this case.
> */
> - spin_lock(&log->l_icloglock);
> - xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt);
> - *record_cnt = 0;
> - *data_cnt = 0;
> - goto release_iclog;
> - }
> + if (lv->lv_niovecs &&
> + lv->lv_bytes > iclog->ic_size - *log_offset)
> + break;
>
> - *partial_copy = 0;
> - *partial_copy_len = 0;
> + /*
> + * Ordered log vectors have no regions to write so this
> + * loop will naturally skip them.
> + */
> + for (index = 0; index < lv->lv_niovecs; index++) {
> + struct xfs_log_iovec *reg = &lv->lv_iovecp[index];
> + struct xlog_op_header *ophdr = reg->i_addr;
>
> - if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
> - /* no more space in this iclog - push it. */
> - spin_lock(&log->l_icloglock);
> - xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt);
> - *record_cnt = 0;
> - *data_cnt = 0;
> + ASSERT(reg->i_len % sizeof(int32_t) == 0);
> + ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);
>
> - if (iclog->ic_state == XLOG_STATE_ACTIVE)
> - xlog_state_switch_iclogs(log, iclog, 0);
> - else
> - ASSERT(iclog->ic_state == XLOG_STATE_WANT_SYNC ||
> - iclog->ic_state == XLOG_STATE_IOERROR);
> - if (!commit_iclog)
> - goto release_iclog;
> - spin_unlock(&log->l_icloglock);
> - ASSERT(flags & XLOG_COMMIT_TRANS);
> - *commit_iclog = iclog;
> + ophdr->oh_tid = cpu_to_be32(ticket->t_tid);
> + ophdr->oh_len = cpu_to_be32(reg->i_len -
> + sizeof(struct xlog_op_header));
> + memcpy(ptr, reg->i_addr, reg->i_len);
> + xlog_write_adv_cnt(&ptr, len, log_offset, reg->i_len);
> + (*record_cnt)++;
> + *data_cnt += reg->i_len;
> + }
> }
> + ASSERT(*len == 0 || lv);
> + return lv;
> +}
>
> - return 0;
> +static int
> +xlog_write_get_more_iclog_space(
> + struct xlog *log,
> + struct xlog_ticket *ticket,
> + struct xlog_in_core **iclogp,
> + uint32_t *log_offset,
> + uint32_t len,
> + uint32_t *record_cnt,
> + uint32_t *data_cnt,
> + int *contwr)
> +{
> + struct xlog_in_core *iclog = *iclogp;
> + int error;
>
> -release_iclog:
> + spin_lock(&log->l_icloglock);
> + xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt);
> + ASSERT(iclog->ic_state == XLOG_STATE_WANT_SYNC ||
> + iclog->ic_state == XLOG_STATE_IOERROR);
> error = xlog_state_release_iclog(log, iclog);
> spin_unlock(&log->l_icloglock);
> - return error;
> + if (error)
> + return error;
> +
> + error = xlog_state_get_iclog_space(log, len, &iclog,
> + ticket, contwr, log_offset);
> + if (error)
> + return error;
> + *record_cnt = 0;
> + *data_cnt = 0;
> + *iclogp = iclog;
> + return 0;
> }
>
> /*
> - * Write log vectors into a single iclog which is guaranteed by the caller
> - * to have enough space to write the entire log vector into. Return the number
> - * of log vectors written into the iclog.
> + * Write log vectors into a single iclog which is smaller than the current chain
> + * length. We write until we cannot fit a full record into the remaining space
> + * and then stop. We return the log vector that is to be written that cannot
> + * wholly fit in the iclog.
> */
> -static int
> -xlog_write_single(
> +static struct xfs_log_vec *
> +xlog_write_partial(
> + struct xlog *log,
> struct xfs_log_vec *log_vector,
> struct xlog_ticket *ticket,
> - struct xlog_in_core *iclog,
> - uint32_t log_offset,
> - uint32_t len)
> + struct xlog_in_core **iclogp,
> + uint32_t *log_offset,
> + uint32_t *len,
> + uint32_t *record_cnt,
> + uint32_t *data_cnt,
> + int *contwr)
> {
> - struct xfs_log_vec *lv;
> + struct xlog_in_core *iclog = *iclogp;
> + struct xfs_log_vec *lv = log_vector;
> + struct xfs_log_iovec *reg;
> + struct xlog_op_header *ophdr;
> void *ptr;
> int index = 0;
> - int record_cnt = 0;
> + uint32_t rlen;
> + int error;
>
> - ASSERT(log_offset + len <= iclog->ic_size);
> + /* walk the logvec, copying until we run out of space in the iclog */
> + ptr = iclog->ic_datap + *log_offset;
> + for (index = 0; index < lv->lv_niovecs; index++) {
> + uint32_t reg_offset = 0;
> +
> + reg = &lv->lv_iovecp[index];
> + ASSERT(reg->i_len % sizeof(int32_t) == 0);
>
> - ptr = iclog->ic_datap + log_offset;
> - for (lv = log_vector; lv; lv = lv->lv_next) {
> /*
> - * Ordered log vectors have no regions to write so this
> - * loop will naturally skip them.
> + * The first region of a continuation must have a non-zero
> + * length otherwise log recovery will just skip over it and
> + * start recovering from the next opheader it finds. Because we
> + * mark the next opheader as a continuation, recovery will then
> + * incorrectly add the continuation to the previous region and
> + * that breaks stuff.
> + *
> + * Hence if there isn't space for region data after the
> + * opheader, then we need to start afresh with a new iclog.
> */
> - for (index = 0; index < lv->lv_niovecs; index++) {
> - struct xfs_log_iovec *reg = &lv->lv_iovecp[index];
> - struct xlog_op_header *ophdr = reg->i_addr;
> + if (iclog->ic_size - *log_offset <=
> + sizeof(struct xlog_op_header)) {
> + error = xlog_write_get_more_iclog_space(log, ticket,
> + &iclog, log_offset, *len, record_cnt,
> + data_cnt, contwr);
> + if (error)
> + return ERR_PTR(error);
> + ptr = iclog->ic_datap + *log_offset;
> + }
>
> - ASSERT(reg->i_len % sizeof(int32_t) == 0);
> - ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);
> + ophdr = reg->i_addr;
> + rlen = min_t(uint32_t, reg->i_len, iclog->ic_size - *log_offset);
> +
> + ophdr->oh_tid = cpu_to_be32(ticket->t_tid);
> + ophdr->oh_len = cpu_to_be32(rlen - sizeof(struct xlog_op_header));
> + if (rlen != reg->i_len)
> + ophdr->oh_flags |= XLOG_CONTINUE_TRANS;
> +
> + ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);
> + xlog_verify_dest_ptr(log, ptr);
> + memcpy(ptr, reg->i_addr, rlen);
> + xlog_write_adv_cnt(&ptr, len, log_offset, rlen);
> + (*record_cnt)++;
> + *data_cnt += rlen;
> +
> + /* If we wrote the whole region, move to the next. */
> + if (rlen == reg->i_len)
> + continue;
> +
> + /*
> + * We now have a partially written iovec, but it can span
> + * multiple iclogs so we loop here. First we release the iclog
> + * we currently have, then we get a new iclog and add a new
> + * opheader. Then we continue copying from where we were until
> + * we either complete the iovec or fill the iclog. If we
> + * complete the iovec, then we increment the index and go right
> + * back to the top of the outer loop. if we fill the iclog, we
> + * run the inner loop again.
> + *
> + * This is complicated by the tail of a region using all the
> + * space in an iclog and hence requiring us to release the iclog
> + * and get a new one before returning to the outer loop. We must
> + * always guarantee that we exit this inner loop with at least
> + * space for log transaction opheaders left in the current
> + * iclog, hence we cannot just terminate the loop at the end
> + * of the of the continuation. So we loop while there is no
> + * space left in the current iclog, and check for the end of the
> + * continuation after getting a new iclog.
> + */
> + do {
> + /*
> + * Account for the continuation opheader before we get
> + * a new iclog. This is necessary so that we reserve
> + * space in the iclog for it.
> + */
> + *len += sizeof(struct xlog_op_header);
> + ticket->t_curr_res -= sizeof(struct xlog_op_header);
> +
> + error = xlog_write_get_more_iclog_space(log, ticket,
> + &iclog, log_offset, *len, record_cnt,
> + data_cnt, contwr);
> + if (error)
> + return ERR_PTR(error);
> + ptr = iclog->ic_datap + *log_offset;
>
> + ophdr = ptr;
> ophdr->oh_tid = cpu_to_be32(ticket->t_tid);
> - ophdr->oh_len = cpu_to_be32(reg->i_len -
> + ophdr->oh_clientid = XFS_TRANSACTION;
> + ophdr->oh_res2 = 0;
> + ophdr->oh_flags = XLOG_WAS_CONT_TRANS;
> +
> + xlog_write_adv_cnt(&ptr, len, log_offset,
> sizeof(struct xlog_op_header));
> - memcpy(ptr, reg->i_addr, reg->i_len);
> - xlog_write_adv_cnt(&ptr, &len, &log_offset, reg->i_len);
> - record_cnt++;
> - }
> + *data_cnt += sizeof(struct xlog_op_header);
> +
> + /*
> + * If rlen fits in the iclog, then end the region
> + * continuation. Otherwise we're going around again.
> + */
> + reg_offset += rlen;
> + rlen = reg->i_len - reg_offset;
> + if (rlen <= iclog->ic_size - *log_offset)
> + ophdr->oh_flags |= XLOG_END_TRANS;
> + else
> + ophdr->oh_flags |= XLOG_CONTINUE_TRANS;
> +
> + rlen = min_t(uint32_t, rlen, iclog->ic_size - *log_offset);
> + ophdr->oh_len = cpu_to_be32(rlen);
> +
> + xlog_verify_dest_ptr(log, ptr);
> + memcpy(ptr, reg->i_addr + reg_offset, rlen);
> + xlog_write_adv_cnt(&ptr, len, log_offset, rlen);
> + (*record_cnt)++;
> + *data_cnt += rlen;
> +
> + } while (ophdr->oh_flags & XLOG_CONTINUE_TRANS);
> }
> - ASSERT(len == 0);
> - return record_cnt;
> -}
>
> + /*
> + * No more iovecs remain in this logvec so return the next log vec to
> + * the caller so it can go back to fast path copying.
> + */
> + *iclogp = iclog;
> + return lv->lv_next;
> +}
>
> /*
> * Write some region out to in-core log
> @@ -2323,14 +2407,11 @@ xlog_write(
> {
> struct xlog_in_core *iclog = NULL;
> struct xfs_log_vec *lv = log_vector;
> - struct xfs_log_iovec *vecp = lv->lv_iovecp;
> - int index = 0;
> - int partial_copy = 0;
> - int partial_copy_len = 0;
> int contwr = 0;
> int record_cnt = 0;
> int data_cnt = 0;
> int error = 0;
> + int log_offset;
>
> if (ticket->t_curr_res < 0) {
> xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
> @@ -2339,146 +2420,40 @@ xlog_write(
> xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
> }
>
> - if (start_lsn)
> - *start_lsn = 0;
> - while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
> - void *ptr;
> - int log_offset;
> -
> - error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
> - &contwr, &log_offset);
> - if (error)
> - return error;
> -
> - ASSERT(log_offset <= iclog->ic_size - 1);
> + error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
> + &contwr, &log_offset);
> + if (error)
> + return error;
>
> - /* Start_lsn is the first lsn written to. */
> - if (start_lsn && !*start_lsn)
> - *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn);
> + /* start_lsn is the LSN of the first iclog written to. */
> + if (start_lsn)
> + *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn);
>
> - /* If this is a single iclog write, go fast... */
> - if (!contwr && lv == log_vector) {
> - record_cnt = xlog_write_single(lv, ticket, iclog,
> - log_offset, len);
> - len = 0;
> - data_cnt = len;
> + while (lv) {
> + lv = xlog_write_single(lv, ticket, iclog, &log_offset,
> + &len, &record_cnt, &data_cnt);
> + if (!lv)
> break;
> - }
> -
> - /*
> - * This loop writes out as many regions as can fit in the amount
> - * of space which was allocated by xlog_state_get_iclog_space().
> - */
> - ptr = iclog->ic_datap + log_offset;
> - while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
> - struct xfs_log_iovec *reg;
> - struct xlog_op_header *ophdr;
> - int copy_len;
> - int copy_off;
> - bool ordered = false;
> - bool added_ophdr = false;
> -
> - /* ordered log vectors have no regions to write */
> - if (lv->lv_buf_len == XFS_LOG_VEC_ORDERED) {
> - ASSERT(lv->lv_niovecs == 0);
> - ordered = true;
> - goto next_lv;
> - }
> -
> - reg = &vecp[index];
> - ASSERT(reg->i_len % sizeof(int32_t) == 0);
> - ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);
> -
> - /*
> - * Regions always have their ophdr at the start of the
> - * region, except for:
> - * - a transaction start which has a start record ophdr
> - * before the first region ophdr; and
> - * - the previous region didn't fully fit into an iclog
> - * so needs a continuation ophdr to prepend the region
> - * in this new iclog.
> - */
> - ophdr = reg->i_addr;
> - if (optype && index) {
> - optype &= ~XLOG_START_TRANS;
> - } else if (partial_copy) {
> - ophdr = xlog_write_setup_ophdr(ptr, ticket);
> - xlog_write_adv_cnt(&ptr, &len, &log_offset,
> - sizeof(struct xlog_op_header));
> - added_ophdr = true;
> - }
> - ophdr->oh_tid = cpu_to_be32(ticket->t_tid);
> -
> - len += xlog_write_setup_copy(ticket, ophdr,
> - iclog->ic_size-log_offset,
> - reg->i_len,
> - ©_off, ©_len,
> - &partial_copy,
> - &partial_copy_len);
> - xlog_verify_dest_ptr(log, ptr);
>
> -
> - /*
> - * Wart: need to update length in embedded ophdr not
> - * to include it's own length.
> - */
> - if (!added_ophdr) {
> - ophdr->oh_len = cpu_to_be32(copy_len -
> - sizeof(struct xlog_op_header));
> - }
> -
> - ASSERT(copy_len > 0);
> - memcpy(ptr, reg->i_addr + copy_off, copy_len);
> - xlog_write_adv_cnt(&ptr, &len, &log_offset, copy_len);
> -
> - if (added_ophdr)
> - copy_len += sizeof(struct xlog_op_header);
> - record_cnt++;
> - data_cnt += contwr ? copy_len : 0;
> -
> - error = xlog_write_copy_finish(log, iclog, optype,
> - &record_cnt, &data_cnt,
> - &partial_copy,
> - &partial_copy_len,
> - log_offset,
> - commit_iclog);
> - if (error)
> - return error;
> -
> - /*
> - * if we had a partial copy, we need to get more iclog
> - * space but we don't want to increment the region
> - * index because there is still more is this region to
> - * write.
> - *
> - * If we completed writing this region, and we flushed
> - * the iclog (indicated by resetting of the record
> - * count), then we also need to get more log space. If
> - * this was the last record, though, we are done and
> - * can just return.
> - */
> - if (partial_copy)
> - break;
> -
> - if (++index == lv->lv_niovecs) {
> -next_lv:
> - lv = lv->lv_next;
> - index = 0;
> - if (lv)
> - vecp = lv->lv_iovecp;
> - }
> - if (record_cnt == 0 && !ordered) {
> - if (!lv)
> - return 0;
> - break;
> - }
> + ASSERT(!(optype & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS)));
> + lv = xlog_write_partial(log, lv, ticket, &iclog, &log_offset,
> + &len, &record_cnt, &data_cnt, &contwr);
> + if (IS_ERR_OR_NULL(lv)) {
> + error = PTR_ERR_OR_ZERO(lv);
> + break;
> }
> }
> + ASSERT((len == 0 && !lv) || error);
>
> - ASSERT(len == 0);
> -
> + /*
> + * We've already been guaranteed that the last writes will fit inside
> + * the current iclog, and hence it will already have the space used by
> + * those writes accounted to it. Hence we do not need to update the
> + * iclog with the number of bytes written here.
> + */
> + ASSERT(!contwr || XLOG_FORCED_SHUTDOWN(log));
> spin_lock(&log->l_icloglock);
> - xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
> + xlog_state_finish_copy(log, iclog, record_cnt, 0);
> if (commit_iclog) {
> ASSERT(optype & XLOG_COMMIT_TRANS);
> *commit_iclog = iclog;
> @@ -3633,11 +3608,12 @@ xlog_verify_iclog(
> iclog->ic_header.h_cycle_data[idx]);
> }
> }
> - if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
> + if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) {
> xfs_warn(log->l_mp,
> - "%s: invalid clientid %d op "PTR_FMT" offset 0x%lx",
> - __func__, clientid, ophead,
> + "%s: op %d invalid clientid %d op "PTR_FMT" offset 0x%lx",
> + __func__, i, clientid, ophead,
> (unsigned long)field_offset);
> + }
>
> /* check length */
> p = &ophead->oh_len;
> --
> 2.31.1
>
next prev parent reply other threads:[~2021-05-27 18:07 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 [this message]
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
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
-- strict thread matches above, loose matches on Subject: below --
2021-06-03 5:22 [PATCH 00/39 v5] xfs: CIL and log optimisations Dave Chinner
2021-06-03 5:22 ` [PATCH 22/39] xfs:_introduce xlog_write_partial() 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=20210527180659.GD2402049@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).