xfs: introduce xlog_write_full()

Introduce an optimised version of xlog_write() that is used when the
entire write will fit in a single iclog. This greatly simplifies the
implementation of writing a log vector chain into an iclog, and sets
the ground work for a much more understandable xlog_write()
implementation.

This incorporates some factoring and simplifications proposed by
Christoph Hellwig.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Chandan Babu R <chandan.babu@oracle.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Dave Chinner 2022-04-21 10:36:05 +10:00 committed by Dave Chinner
parent decb545fc0
commit db357078b0
1 changed files with 66 additions and 3 deletions

View File

@ -2210,6 +2210,58 @@ xlog_print_trans(
}
}
static inline void
xlog_write_iovec(
struct xlog_in_core *iclog,
uint32_t *log_offset,
void *data,
uint32_t write_len,
int *bytes_left,
uint32_t *record_cnt,
uint32_t *data_cnt)
{
ASSERT(*log_offset % sizeof(int32_t) == 0);
ASSERT(write_len % sizeof(int32_t) == 0);
memcpy(iclog->ic_datap + *log_offset, data, write_len);
*log_offset += write_len;
*bytes_left -= write_len;
(*record_cnt)++;
*data_cnt += write_len;
}
/*
* Write log vectors into a single iclog which is guaranteed by the caller
* to have enough space to write the entire log vector into.
*/
static void
xlog_write_full(
struct xfs_log_vec *lv,
struct xlog_ticket *ticket,
struct xlog_in_core *iclog,
uint32_t *log_offset,
uint32_t *len,
uint32_t *record_cnt,
uint32_t *data_cnt)
{
int index;
ASSERT(*log_offset + *len <= iclog->ic_size);
/*
* 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;
ophdr->oh_tid = cpu_to_be32(ticket->t_tid);
xlog_write_iovec(iclog, log_offset, reg->i_addr,
reg->i_len, len, record_cnt, data_cnt);
}
}
static xlog_op_header_t *
xlog_write_setup_ophdr(
struct xlog_op_header *ophdr,
@ -2374,8 +2426,8 @@ xlog_write(
int partial_copy = 0;
int partial_copy_len = 0;
int contwr = 0;
int record_cnt = 0;
int data_cnt = 0;
uint32_t record_cnt = 0;
uint32_t data_cnt = 0;
int error = 0;
if (ticket->t_curr_res < 0) {
@ -2395,7 +2447,6 @@ xlog_write(
return error;
ASSERT(log_offset <= iclog->ic_size - 1);
ptr = iclog->ic_datap + log_offset;
/*
* If we have a context pointer, pass it the first iclog we are
@ -2407,10 +2458,22 @@ xlog_write(
ctx = NULL;
}
/* If this is a single iclog write, go fast... */
if (!contwr && lv == log_vector) {
while (lv) {
xlog_write_full(lv, ticket, iclog, &log_offset,
&len, &record_cnt, &data_cnt);
lv = lv->lv_next;
}
data_cnt = 0;
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;