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:
parent
decb545fc0
commit
db357078b0
@ -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 *
|
static xlog_op_header_t *
|
||||||
xlog_write_setup_ophdr(
|
xlog_write_setup_ophdr(
|
||||||
struct xlog_op_header *ophdr,
|
struct xlog_op_header *ophdr,
|
||||||
@ -2374,8 +2426,8 @@ xlog_write(
|
|||||||
int partial_copy = 0;
|
int partial_copy = 0;
|
||||||
int partial_copy_len = 0;
|
int partial_copy_len = 0;
|
||||||
int contwr = 0;
|
int contwr = 0;
|
||||||
int record_cnt = 0;
|
uint32_t record_cnt = 0;
|
||||||
int data_cnt = 0;
|
uint32_t data_cnt = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (ticket->t_curr_res < 0) {
|
if (ticket->t_curr_res < 0) {
|
||||||
@ -2395,7 +2447,6 @@ xlog_write(
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
ASSERT(log_offset <= iclog->ic_size - 1);
|
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
|
* If we have a context pointer, pass it the first iclog we are
|
||||||
@ -2407,10 +2458,22 @@ xlog_write(
|
|||||||
ctx = NULL;
|
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
|
* This loop writes out as many regions as can fit in the amount
|
||||||
* of space which was allocated by xlog_state_get_iclog_space().
|
* 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)) {
|
while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
|
||||||
struct xfs_log_iovec *reg;
|
struct xfs_log_iovec *reg;
|
||||||
struct xlog_op_header *ophdr;
|
struct xlog_op_header *ophdr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user