Commit 7ec94921 authored by Dave Chinner's avatar Dave Chinner Committed by Darrick J. Wong
Browse files

xfs: don't try to write a start record into every iclog



The xlog_write() function iterates over iclogs until it completes
writing all the log vectors passed in. The ticket tracks whether
a start record has been written or not, so only the first iclog gets
a start record. We only ever pass single use tickets to
xlog_write() so we only ever need to write a start record once per
xlog_write() call.

Hence we don't need to store whether we should write a start record
in the ticket as the callers provide all the information we need to
determine if a start record should be written. For the moment, we
have to ensure that we clear the XLOG_TIC_INITED appropriately so
the code in xfs_log_done() still works correctly for committing
transactions.

(darrick: Note the slight behavior change that we always deduct the
size of the op header from the ticket, even for unmount records)

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
[hch: pass an explicit need_start_rec argument]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent f8e566c0
Loading
Loading
Loading
Loading
+37 −40
Original line number Diff line number Diff line
@@ -921,7 +921,7 @@ xfs_log_write_unmount_record(
	/* remove inited flag, and account for space used */
	tic->t_flags = 0;
	tic->t_curr_res -= sizeof(magic);
	error = xlog_write(log, &vec, tic, &lsn, NULL, flags);
	error = xlog_write(log, &vec, tic, &lsn, NULL, flags, false);
	/*
	 * At this point, we're umounting anyway, so there's no point in
	 * transitioning log state to IOERROR. Just continue...
@@ -1541,7 +1541,7 @@ xlog_commit_record(

	ASSERT_ALWAYS(iclog);
	error = xlog_write(log, &vec, ticket, commitlsnp, iclog,
					XLOG_COMMIT_TRANS);
					XLOG_COMMIT_TRANS, false);
	if (error)
		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
	return error;
@@ -2118,23 +2118,21 @@ xlog_print_trans(
}

/*
 * Calculate the potential space needed by the log vector.  Each region gets
 * its own xlog_op_header_t and may need to be double word aligned.
 * Calculate the potential space needed by the log vector.  We may need a start
 * record, and each region gets its own struct xlog_op_header and may need to be
 * double word aligned.
 */
static int
xlog_write_calc_vec_length(
	struct xlog_ticket	*ticket,
	struct xfs_log_vec	*log_vector)
	struct xfs_log_vec	*log_vector,
	bool			need_start_rec)
{
	struct xfs_log_vec	*lv;
	int			headers = 0;
	int			headers = need_start_rec ? 1 : 0;
	int			len = 0;
	int			i;

	/* acct for start rec of xact */
	if (ticket->t_flags & XLOG_TIC_INITED)
		headers++;

	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)
@@ -2156,27 +2154,16 @@ xlog_write_calc_vec_length(
	return len;
}

/*
 * If first write for transaction, insert start record  We can't be trying to
 * commit if we are inited.  We can't have any "partial_copy" if we are inited.
 */
static int
static void
xlog_write_start_rec(
	struct xlog_op_header	*ophdr,
	struct xlog_ticket	*ticket)
{
	if (!(ticket->t_flags & XLOG_TIC_INITED))
		return 0;

	ophdr->oh_tid	= cpu_to_be32(ticket->t_tid);
	ophdr->oh_clientid = ticket->t_clientid;
	ophdr->oh_len = 0;
	ophdr->oh_flags = XLOG_START_TRANS;
	ophdr->oh_res2 = 0;

	ticket->t_flags &= ~XLOG_TIC_INITED;

	return sizeof(struct xlog_op_header);
}

static xlog_op_header_t *
@@ -2365,7 +2352,8 @@ xlog_write(
	struct xlog_ticket	*ticket,
	xfs_lsn_t		*start_lsn,
	struct xlog_in_core	**commit_iclog,
	uint			flags)
	uint			flags,
	bool			need_start_rec)
{
	struct xlog_in_core	*iclog = NULL;
	struct xfs_log_iovec	*vecp;
@@ -2381,23 +2369,22 @@ xlog_write(

	*start_lsn = 0;

	len = xlog_write_calc_vec_length(ticket, log_vector);

	/*
	 * Region headers and bytes are already accounted for.
	 * We only need to take into account start records and
	 * split regions in this function.
	 * Region headers and bytes are already accounted for.  We only need to
	 * take into account start records and split regions in this function.
	 */
	if (ticket->t_flags & XLOG_TIC_INITED)
		ticket->t_curr_res -= sizeof(xlog_op_header_t);
	if (ticket->t_flags & XLOG_TIC_INITED) {
		ticket->t_curr_res -= sizeof(struct xlog_op_header);
		ticket->t_flags &= ~XLOG_TIC_INITED;
	}

	/*
	 * Commit record headers need to be accounted for. These
	 * come in as separate writes so are easy to detect.
	 * Commit record headers and unmount records need to be accounted for.
	 * These come in as separate writes so are easy to detect.
	 */
	if (flags & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS))
		ticket->t_curr_res -= sizeof(xlog_op_header_t);

	if (!need_start_rec)
		ticket->t_curr_res -= sizeof(struct xlog_op_header);
	if (ticket->t_curr_res < 0) {
		xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
		     "ctx ticket reservation ran out. Need to up reservation");
@@ -2405,6 +2392,8 @@ xlog_write(
		xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
	}

	len = xlog_write_calc_vec_length(ticket, log_vector, need_start_rec);

	index = 0;
	lv = log_vector;
	vecp = lv->lv_iovecp;
@@ -2431,7 +2420,6 @@ xlog_write(
		while (lv && (!lv->lv_niovecs || index < lv->lv_niovecs)) {
			struct xfs_log_iovec	*reg;
			struct xlog_op_header	*ophdr;
			int			start_rec_copy;
			int			copy_len;
			int			copy_off;
			bool			ordered = false;
@@ -2447,11 +2435,15 @@ xlog_write(
			ASSERT(reg->i_len % sizeof(int32_t) == 0);
			ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);

			start_rec_copy = xlog_write_start_rec(ptr, ticket);
			if (start_rec_copy) {
				record_cnt++;
			/*
			 * Before we start formatting log vectors, we need to
			 * write a start record. Only do this for the first
			 * iclog we write to.
			 */
			if (need_start_rec) {
				xlog_write_start_rec(ptr, ticket);
				xlog_write_adv_cnt(&ptr, &len, &log_offset,
						   start_rec_copy);
						sizeof(struct xlog_op_header));
			}

			ophdr = xlog_write_setup_ophdr(log, ptr, ticket, flags);
@@ -2483,8 +2475,13 @@ xlog_write(
				xlog_write_adv_cnt(&ptr, &len, &log_offset,
						   copy_len);
			}
			copy_len += start_rec_copy + sizeof(xlog_op_header_t);
			copy_len += sizeof(struct xlog_op_header);
			record_cnt++;
			if (need_start_rec) {
				copy_len += sizeof(struct xlog_op_header);
				record_cnt++;
				need_start_rec = false;
			}
			data_cnt += contwr ? copy_len : 0;

			error = xlog_write_copy_finish(log, iclog, flags,
+1 −1
Original line number Diff line number Diff line
@@ -801,7 +801,7 @@ xlog_cil_push_work(
	lvhdr.lv_iovecp = &lhdr;
	lvhdr.lv_next = ctx->lv_chain;

	error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL, 0);
	error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL, 0, true);
	if (error)
		goto out_abort_free_ticket;

+4 −8
Original line number Diff line number Diff line
@@ -439,14 +439,10 @@ xlog_write_adv_cnt(void **ptr, int *len, int *off, size_t bytes)

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_log_vec	*log_vector,
	struct xlog_ticket	*tic,
	xfs_lsn_t		*start_lsn,
	struct xlog_in_core	**commit_iclog,
	uint			flags);
int	xlog_write(struct xlog *log, struct xfs_log_vec *log_vector,
		struct xlog_ticket *tic, xfs_lsn_t *start_lsn,
		struct xlog_in_core **commit_iclog, uint flags,
		bool need_start_rec);

/*
 * When we crack an atomic LSN, we sample it first so that the value will not