summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r--fs/xfs/xfs_log.c90
1 files changed, 45 insertions, 45 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 499e15b24215..f6fa5426278b 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -2221,9 +2221,9 @@ xlog_print_trans(
}
/*
- * 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.
+ * Calculate the potential space needed by the log vector. If this is a start
+ * transaction, the caller has already accounted for both opheaders in the start
+ * transaction, so we don't need to account for them here.
*/
static int
xlog_write_calc_vec_length(
@@ -2236,9 +2236,6 @@ xlog_write_calc_vec_length(
int len = 0;
int i;
- if (optype & XLOG_START_TRANS)
- 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)
@@ -2254,24 +2251,20 @@ xlog_write_calc_vec_length(
}
}
+ /* Don't account for regions with embedded ophdrs */
+ if (optype && headers > 0) {
+ if (optype & XLOG_START_TRANS) {
+ ASSERT(headers >= 2);
+ headers -= 2;
+ }
+ }
+
ticket->t_res_num_ophdrs += headers;
len += headers * sizeof(struct xlog_op_header);
return len;
}
-static void
-xlog_write_start_rec(
- struct xlog_op_header *ophdr,
- struct xlog_ticket *ticket)
-{
- 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;
-}
-
static xlog_op_header_t *
xlog_write_setup_ophdr(
struct xlog *log,
@@ -2467,9 +2460,11 @@ xlog_write(
* If this is a commit or unmount transaction, we don't need a start
* record to be written. We do, however, have to account for the
* commit or unmount header that gets written. Hence we always have
- * to account for an extra xlog_op_header here.
+ * to account for an extra xlog_op_header here for commit and unmount
+ * records.
*/
- ticket->t_curr_res -= sizeof(struct xlog_op_header);
+ if (optype & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS))
+ 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");
@@ -2510,7 +2505,7 @@ xlog_write(
int copy_len;
int copy_off;
bool ordered = false;
- bool wrote_start_rec = false;
+ bool added_ophdr = false;
/* ordered log vectors have no regions to write */
if (lv->lv_buf_len == XFS_LOG_VEC_ORDERED) {
@@ -2524,25 +2519,24 @@ xlog_write(
ASSERT((unsigned long)ptr % sizeof(int32_t) == 0);
/*
- * Before we start formatting log vectors, we need to
- * write a start record. Only do this for the first
- * iclog we write to.
+ * The XLOG_START_TRANS has embedded ophdrs for the
+ * start record and transaction header. They will always
+ * be the first two regions in the lv chain.
*/
if (optype & XLOG_START_TRANS) {
- xlog_write_start_rec(ptr, ticket);
- xlog_write_adv_cnt(&ptr, &len, &log_offset,
- sizeof(struct xlog_op_header));
- optype &= ~XLOG_START_TRANS;
- wrote_start_rec = true;
- }
-
- ophdr = xlog_write_setup_ophdr(log, ptr, ticket, optype);
- if (!ophdr)
- return -EIO;
+ ophdr = reg->i_addr;
+ if (index)
+ optype &= ~XLOG_START_TRANS;
+ } else {
+ ophdr = xlog_write_setup_ophdr(log, ptr,
+ ticket, optype);
+ if (!ophdr)
+ return -EIO;
- xlog_write_adv_cnt(&ptr, &len, &log_offset,
+ xlog_write_adv_cnt(&ptr, &len, &log_offset,
sizeof(struct xlog_op_header));
-
+ added_ophdr = true;
+ }
len += xlog_write_setup_copy(ticket, ophdr,
iclog->ic_size-log_offset,
reg->i_len,
@@ -2551,13 +2545,22 @@ xlog_write(
&partial_copy_len);
xlog_verify_dest_ptr(log, ptr);
+
+ /*
+ * Wart: need to update length in embedded ophdr not
+ * to include it's own length.
+ */
+ if (!added_ophdr) {
+ ophdr->oh_len = cpu_to_be32(copy_len -
+ sizeof(struct xlog_op_header));
+ }
/*
* Copy region.
*
- * Unmount records just log an opheader, so can have
- * empty payloads with no data region to copy. Hence we
- * only copy the payload if the vector says it has data
- * to copy.
+ * Commit and unmount records just log an opheader, so
+ * we can have empty payloads with no data region to
+ * copy. Hence we only copy the payload if the vector
+ * says it has data to copy.
*/
ASSERT(copy_len >= 0);
if (copy_len > 0) {
@@ -2565,12 +2568,9 @@ xlog_write(
xlog_write_adv_cnt(&ptr, &len, &log_offset,
copy_len);
}
- copy_len += sizeof(struct xlog_op_header);
- record_cnt++;
- if (wrote_start_rec) {
+ if (added_ophdr)
copy_len += sizeof(struct xlog_op_header);
- record_cnt++;
- }
+ record_cnt++;
data_cnt += contwr ? copy_len : 0;
error = xlog_write_copy_finish(log, iclog, optype,