Commit d80fc291 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner
Browse files

xfs: pass lv chain length into xlog_write()



The caller of xlog_write() usually has a close accounting of the
aggregated vector length contained in the log vector chain passed to
xlog_write(). There is no need to iterate the chain to calculate he
length of the data in xlog_write_calculate_len() if the caller is
already iterating that chain to build it.

Passing in the vector length avoids doing an extra chain iteration,
which can be a significant amount of work given that large CIL
commits can have hundreds of thousands of vectors attached to the
chain.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarChandan Babu R <chandan.babu@oracle.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent c5141320
Loading
Loading
Loading
Loading
+5 −30
Original line number Diff line number Diff line
@@ -958,7 +958,8 @@ xlog_write_unmount_record(
	/* account for space used by record data */
	ticket->t_curr_res -= sizeof(unmount_rec);

	return xlog_write(log, NULL, &vec, ticket, XLOG_UNMOUNT_TRANS);
	return xlog_write(log, NULL, &vec, ticket, XLOG_UNMOUNT_TRANS,
			reg.i_len);
}

/*
@@ -2209,32 +2210,6 @@ xlog_print_trans(
	}
}

/*
 * Calculate the potential space needed by the log vector. All regions contain
 * their own opheaders and they are accounted for in region space so we don't
 * need to add them to the vector length here.
 */
static int
xlog_write_calc_vec_length(
	struct xlog_ticket	*ticket,
	struct xfs_log_vec	*log_vector,
	uint			optype)
{
	struct xfs_log_vec	*lv;
	int			len = 0;
	int			i;

	for (lv = log_vector; lv; lv = lv->lv_next) {
		/* we don't write ordered log vectors */
		if (lv->lv_buf_len == XFS_LOG_VEC_ORDERED)
			continue;

		for (i = 0; i < lv->lv_niovecs; i++)
			len += lv->lv_iovecp[i].i_len;
	}
	return len;
}

static xlog_op_header_t *
xlog_write_setup_ophdr(
	struct xlog_op_header	*ophdr,
@@ -2388,13 +2363,14 @@ xlog_write(
	struct xfs_cil_ctx	*ctx,
	struct xfs_log_vec	*log_vector,
	struct xlog_ticket	*ticket,
	uint			optype)
	uint			optype,
	uint32_t		len)

{
	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			len;
	int			partial_copy = 0;
	int			partial_copy_len = 0;
	int			contwr = 0;
@@ -2409,7 +2385,6 @@ xlog_write(
		xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
	}

	len = xlog_write_calc_vec_length(ticket, log_vector, optype);
	while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
		void		*ptr;
		int		log_offset;
+17 −8
Original line number Diff line number Diff line
@@ -825,7 +825,8 @@ xlog_cil_order_write(
static int
xlog_cil_write_chain(
	struct xfs_cil_ctx	*ctx,
	struct xfs_log_vec	*chain)
	struct xfs_log_vec	*chain,
	uint32_t		chain_len)
{
	struct xlog		*log = ctx->cil->xc_log;
	int			error;
@@ -833,7 +834,8 @@ xlog_cil_write_chain(
	error = xlog_cil_order_write(ctx->cil, ctx->sequence, _START_RECORD);
	if (error)
		return error;
	return xlog_write(log, ctx, chain, ctx->ticket, XLOG_START_TRANS);
	return xlog_write(log, ctx, chain, ctx->ticket, XLOG_START_TRANS,
			chain_len);
}

/*
@@ -872,7 +874,8 @@ xlog_cil_write_commit_record(

	/* account for space used by record data */
	ctx->ticket->t_curr_res -= reg.i_len;
	error = xlog_write(log, ctx, &vec, ctx->ticket, XLOG_COMMIT_TRANS);
	error = xlog_write(log, ctx, &vec, ctx->ticket, XLOG_COMMIT_TRANS,
			reg.i_len);
	if (error)
		xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
	return error;
@@ -935,11 +938,12 @@ xlog_cil_build_trans_hdr(
				sizeof(struct xfs_trans_header);
	hdr->lhdr[1].i_type = XLOG_REG_TYPE_TRANSHDR;

	tic->t_curr_res -= hdr->lhdr[0].i_len + hdr->lhdr[1].i_len;

	lvhdr->lv_niovecs = 2;
	lvhdr->lv_iovecp = &hdr->lhdr[0];
	lvhdr->lv_bytes = hdr->lhdr[0].i_len + hdr->lhdr[1].i_len;
	lvhdr->lv_next = ctx->lv_chain;

	tic->t_curr_res -= lvhdr->lv_bytes;
}

/*
@@ -966,7 +970,8 @@ xlog_cil_push_work(
	struct xlog		*log = cil->xc_log;
	struct xfs_log_vec	*lv;
	struct xfs_cil_ctx	*new_ctx;
	int			num_iovecs;
	int			num_iovecs = 0;
	int			num_bytes = 0;
	int			error = 0;
	struct xlog_cil_trans_hdr thdr;
	struct xfs_log_vec	lvhdr = { NULL };
@@ -1047,7 +1052,6 @@ xlog_cil_push_work(
	 * by the flush lock.
	 */
	lv = NULL;
	num_iovecs = 0;
	while (!list_empty(&cil->xc_cil)) {
		struct xfs_log_item	*item;

@@ -1061,6 +1065,10 @@ xlog_cil_push_work(
		lv = item->li_lv;
		item->li_lv = NULL;
		num_iovecs += lv->lv_niovecs;

		/* we don't write ordered log vectors */
		if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED)
			num_bytes += lv->lv_bytes;
	}

	/*
@@ -1099,8 +1107,9 @@ xlog_cil_push_work(
	 * transaction header here as it is not accounted for in xlog_write().
	 */
	xlog_cil_build_trans_hdr(ctx, &thdr, &lvhdr, num_iovecs);
	num_bytes += lvhdr.lv_bytes;

	error = xlog_cil_write_chain(ctx, &lvhdr);
	error = xlog_cil_write_chain(ctx, &lvhdr, num_bytes);
	if (error)
		goto out_abort_free_ticket;

+1 −1
Original line number Diff line number Diff line
@@ -503,7 +503,7 @@ void xlog_print_tic_res(struct xfs_mount *mp, struct xlog_ticket *ticket);
void	xlog_print_trans(struct xfs_trans *);
int	xlog_write(struct xlog *log, struct xfs_cil_ctx *ctx,
		struct xfs_log_vec *log_vector, struct xlog_ticket *tic,
		uint optype);
		uint optype, uint32_t len);
void	xfs_log_ticket_ungrant(struct xlog *log, struct xlog_ticket *ticket);
void	xfs_log_ticket_regrant(struct xlog *log, struct xlog_ticket *ticket);