From ed6e8e7b03cedaeacf8cdd2b5ad06b45436e92e0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 23 May 2025 05:47:24 +0200 Subject: [PATCH] xfs: improve argument handling for the xlog_write helpers The xlog_write chain passes around the same seven variables that are often passed by reference. Add a xlog_write_data structure to contain them to improve code generation and readability. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_log.c | 171 +++++++++++++++++++---------------------------- 1 file changed, 70 insertions(+), 101 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 562f314a319b..be38d91d1e1b 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -22,6 +22,15 @@ #include "xfs_health.h" #include "xfs_zone_alloc.h" +struct xlog_write_data { + struct xlog_ticket *ticket; + struct xlog_in_core *iclog; + uint32_t bytes_left; + uint32_t record_cnt; + uint32_t data_cnt; + int log_offset; +}; + struct kmem_cache *xfs_log_ticket_cache; /* Local miscellaneous function prototypes */ @@ -43,10 +52,7 @@ STATIC void xlog_state_do_callback( STATIC int xlog_state_get_iclog_space( struct xlog *log, - int len, - struct xlog_in_core **iclog, - struct xlog_ticket *ticket, - int *logoffsetp); + struct xlog_write_data *data); STATIC void xlog_sync( struct xlog *log, @@ -1916,37 +1922,33 @@ xlog_print_trans( static void xlog_write_region( - struct xlog_ticket *ticket, - struct xlog_in_core *iclog, - uint32_t *log_offset, - struct xfs_log_iovec *reg, - int *bytes_left, - uint32_t *record_cnt, - uint32_t *data_cnt) + struct xlog_write_data *data, + struct xfs_log_iovec *reg) { - struct xlog_op_header *ophdr = iclog->ic_datap + *log_offset; + struct xlog_in_core *iclog = data->iclog; + struct xlog_op_header *ophdr = iclog->ic_datap + data->log_offset; uint32_t rlen; - ASSERT(*log_offset < iclog->ic_log->l_iclog_size); - ASSERT(*log_offset % sizeof(int32_t) == 0); + ASSERT(data->log_offset < iclog->ic_log->l_iclog_size); + ASSERT(data->log_offset % sizeof(int32_t) == 0); ASSERT(reg->i_len % sizeof(int32_t) == 0); - *log_offset += sizeof(struct xlog_op_header); - *bytes_left -= sizeof(struct xlog_op_header); - *data_cnt += sizeof(struct xlog_op_header); + data->log_offset += sizeof(struct xlog_op_header); + data->bytes_left -= sizeof(struct xlog_op_header); + data->data_cnt += sizeof(struct xlog_op_header); - ASSERT(iclog->ic_size - *log_offset > 0); - rlen = min_t(uint32_t, reg->i_len, iclog->ic_size - *log_offset); + ASSERT(iclog->ic_size - data->log_offset > 0); + rlen = min_t(uint32_t, reg->i_len, iclog->ic_size - data->log_offset); if (rlen) { - memcpy(iclog->ic_datap + *log_offset, reg->i_addr, rlen); - *log_offset += rlen; - *bytes_left -= rlen; - *data_cnt += rlen; + memcpy(iclog->ic_datap + data->log_offset, reg->i_addr, rlen); + data->log_offset += rlen; + data->bytes_left -= rlen; + data->data_cnt += rlen; reg->i_addr += rlen; reg->i_len -= rlen; } - ophdr->oh_tid = cpu_to_be32(ticket->t_tid); + ophdr->oh_tid = cpu_to_be32(data->ticket->t_tid); ophdr->oh_len = cpu_to_be32(rlen); ophdr->oh_clientid = XFS_TRANSACTION; ophdr->oh_flags = 0; @@ -1978,37 +1980,30 @@ xlog_write_region( break; } - (*record_cnt)++; + data->record_cnt++; } static int xlog_write_get_more_iclog_space( - struct xlog_ticket *ticket, - struct xlog_in_core **iclogp, - uint32_t *log_offset, - uint32_t len, - uint32_t *record_cnt, - uint32_t *data_cnt) + struct xlog_write_data *data) { - struct xlog_in_core *iclog = *iclogp; - struct xlog *log = iclog->ic_log; + struct xlog *log = data->iclog->ic_log; int error; spin_lock(&log->l_icloglock); - ASSERT(iclog->ic_state == XLOG_STATE_WANT_SYNC); - xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt); - error = xlog_state_release_iclog(log, iclog, ticket); + ASSERT(data->iclog->ic_state == XLOG_STATE_WANT_SYNC); + xlog_state_finish_copy(log, data->iclog, data->record_cnt, + data->data_cnt); + error = xlog_state_release_iclog(log, data->iclog, data->ticket); spin_unlock(&log->l_icloglock); if (error) return error; - error = xlog_state_get_iclog_space(log, len, &iclog, ticket, - log_offset); + error = xlog_state_get_iclog_space(log, data); if (error) return error; - *record_cnt = 0; - *data_cnt = 0; - *iclogp = iclog; + data->record_cnt = 0; + data->data_cnt = 0; return 0; } @@ -2027,12 +2022,7 @@ xlog_write_get_more_iclog_space( */ static int xlog_write_remainder( - struct xlog_ticket *ticket, - struct xlog_in_core **iclogp, - uint32_t *log_offset, - uint32_t *len, - uint32_t *record_cnt, - uint32_t *data_cnt, + struct xlog_write_data *data, struct xfs_log_iovec *reg) { int error; @@ -2043,15 +2033,13 @@ xlog_write_remainder( * continuation opheader needs to be accounted to the ticket as the * space it consumes hasn't been accounted to the lv we are writing. */ - *len += sizeof(struct xlog_op_header); - error = xlog_write_get_more_iclog_space(ticket, iclogp, log_offset, - *len, record_cnt, data_cnt); + data->bytes_left += sizeof(struct xlog_op_header); + error = xlog_write_get_more_iclog_space(data); if (error) return error; - xlog_write_region(ticket, *iclogp, log_offset, reg, len, - record_cnt, data_cnt); - ticket->t_curr_res -= sizeof(struct xlog_op_header); + xlog_write_region(data, reg); + data->ticket->t_curr_res -= sizeof(struct xlog_op_header); return 0; } @@ -2063,15 +2051,9 @@ xlog_write_remainder( */ static int xlog_write_vec( - struct xfs_log_vec *lv, - struct xlog_ticket *ticket, - struct xlog_in_core **iclogp, - uint32_t *log_offset, - uint32_t *len, - uint32_t *record_cnt, - uint32_t *data_cnt) + struct xlog_write_data *data, + struct xfs_log_vec *lv) { - struct xlog_in_core *iclog = *iclogp; int index = 0; /* walk the logvec, copying until we run out of space in the iclog */ @@ -2090,11 +2072,9 @@ xlog_write_vec( * Hence if there isn't space for region data after the * opheader, then we need to start afresh with a new iclog. */ - if (iclog->ic_size - *log_offset <= + if (data->iclog->ic_size - data->log_offset <= sizeof(struct xlog_op_header)) { - error = xlog_write_get_more_iclog_space(ticket, - &iclog, log_offset, *len, record_cnt, - data_cnt); + error = xlog_write_get_more_iclog_space(data); if (error) return error; } @@ -2102,8 +2082,7 @@ xlog_write_vec( /* * Write the amount that fits into this iclog. */ - xlog_write_region(ticket, iclog, log_offset, reg, len, - record_cnt, data_cnt); + xlog_write_region(data, reg); /* * We now have an at least partially written iovec, but it can @@ -2111,18 +2090,12 @@ xlog_write_vec( * complete the iovec. */ while (reg->i_len > 0) { - error = xlog_write_remainder(ticket, &iclog, log_offset, - len, record_cnt, data_cnt, reg); + error = xlog_write_remainder(data, reg); if (error) return error; } } - /* - * 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 0; } @@ -2175,12 +2148,12 @@ xlog_write( uint32_t len) { - struct xlog_in_core *iclog = NULL; struct xfs_log_vec *lv; - uint32_t record_cnt = 0; - uint32_t data_cnt = 0; - int error = 0; - int log_offset; + struct xlog_write_data data = { + .ticket = ticket, + .bytes_left = len, + }; + int error; if (ticket->t_curr_res < 0) { xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES, @@ -2189,12 +2162,11 @@ xlog_write( xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR); } - error = xlog_state_get_iclog_space(log, len, &iclog, ticket, - &log_offset); + error = xlog_state_get_iclog_space(log, &data); if (error) return error; - ASSERT(log_offset <= iclog->ic_size - 1); + ASSERT(data.log_offset <= data.iclog->ic_size - 1); /* * If we have a context pointer, pass it the first iclog we are @@ -2202,15 +2174,14 @@ xlog_write( * ordering. */ if (ctx) - xlog_cil_set_ctx_write_state(ctx, iclog); + xlog_cil_set_ctx_write_state(ctx, data.iclog); list_for_each_entry(lv, lv_chain, lv_list) { - error = xlog_write_vec(lv, ticket, &iclog, &log_offset, &len, - &record_cnt, &data_cnt); + error = xlog_write_vec(&data, lv); if (error) return error; } - ASSERT(len == 0); + ASSERT(data.bytes_left == 0); /* * We've already been guaranteed that the last writes will fit inside @@ -2219,8 +2190,8 @@ xlog_write( * iclog with the number of bytes written here. */ spin_lock(&log->l_icloglock); - xlog_state_finish_copy(log, iclog, record_cnt, 0); - error = xlog_state_release_iclog(log, iclog, ticket); + xlog_state_finish_copy(log, data.iclog, data.record_cnt, 0); + error = xlog_state_release_iclog(log, data.iclog, ticket); spin_unlock(&log->l_icloglock); return error; @@ -2542,14 +2513,11 @@ xlog_state_done_syncing( STATIC int xlog_state_get_iclog_space( struct xlog *log, - int len, - struct xlog_in_core **iclogp, - struct xlog_ticket *ticket, - int *logoffsetp) + struct xlog_write_data *data) { - int log_offset; - xlog_rec_header_t *head; - xlog_in_core_t *iclog; + int log_offset; + struct xlog_rec_header *head; + struct xlog_in_core *iclog; restart: spin_lock(&log->l_icloglock); @@ -2580,7 +2548,7 @@ restart: * must be written. */ if (log_offset == 0) { - ticket->t_curr_res -= log->l_iclog_hsize; + data->ticket->t_curr_res -= log->l_iclog_hsize; head->h_cycle = cpu_to_be32(log->l_curr_cycle); head->h_lsn = cpu_to_be64( xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block)); @@ -2609,7 +2577,8 @@ restart: * reference to the iclog. */ if (!atomic_add_unless(&iclog->ic_refcnt, -1, 1)) - error = xlog_state_release_iclog(log, iclog, ticket); + error = xlog_state_release_iclog(log, iclog, + data->ticket); spin_unlock(&log->l_icloglock); if (error) return error; @@ -2622,16 +2591,16 @@ restart: * iclogs (to mark it taken), this particular iclog will release/sync * to disk in xlog_write(). */ - if (len <= iclog->ic_size - iclog->ic_offset) - iclog->ic_offset += len; + if (data->bytes_left <= iclog->ic_size - iclog->ic_offset) + iclog->ic_offset += data->bytes_left; else xlog_state_switch_iclogs(log, iclog, iclog->ic_size); - *iclogp = iclog; + data->iclog = iclog; ASSERT(iclog->ic_offset <= iclog->ic_size); spin_unlock(&log->l_icloglock); - *logoffsetp = log_offset; + data->log_offset = log_offset; return 0; } -- 2.50.1