xfs: dump transaction usage details on log reservation overrun
authorBrian Foster <bfoster@redhat.com>
Thu, 15 Jun 2017 04:29:50 +0000 (21:29 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 19 Jun 2017 15:59:10 +0000 (08:59 -0700)
If a transaction log reservation overrun occurs, the ticket data
associated with the reservation is dumped in xfs_log_commit_cil().
This occurs long after the transaction items and details have been
removed from the transaction and effectively lost. This limited set
of ticket data provides very little information to support debugging
transaction overruns based on the typical report.

To improve transaction log reservation overrun reporting, create a
helper to dump transaction details such as log items, log vector
data, etc., as well as the underlying ticket data for the
transaction. Move the overrun detection from xfs_log_commit_cil() to
xlog_cil_insert_items() so it occurs prior to migration of the
logged items to the CIL. Call the new helper such that it is able to
dump this transaction data before it is lost.

Also, warn on overrun to provide callstack context for the offending
transaction and include a few additional messages from
xlog_cil_insert_items() to display the reservation consumed locally
for overhead such as log vector headers, split region headers and
the context ticket. This provides a complete general breakdown of
the reservation consumption of a transaction when/if it happens to
overrun the reservation.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_log.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h

index 8b283f7cefeafc87d4e3531c4d3eff968f874e5b..c8d0481033479763a88ffdfd6fd98728e59461e2 100644 (file)
@@ -2047,6 +2047,55 @@ xlog_print_tic_res(
        }
 }
 
+/*
+ * Print a summary of the transaction.
+ */
+void
+xlog_print_trans(
+       struct xfs_trans                *tp)
+{
+       struct xfs_mount                *mp = tp->t_mountp;
+       struct xfs_log_item_desc        *lidp;
+
+       /* dump core transaction and ticket info */
+       xfs_warn(mp, "transaction summary:");
+       xfs_warn(mp, "  flags   = 0x%x", tp->t_flags);
+
+       xlog_print_tic_res(mp, tp->t_ticket);
+
+       /* dump each log item */
+       list_for_each_entry(lidp, &tp->t_items, lid_trans) {
+               struct xfs_log_item     *lip = lidp->lid_item;
+               struct xfs_log_vec      *lv = lip->li_lv;
+               struct xfs_log_iovec    *vec;
+               int                     i;
+
+               xfs_warn(mp, "log item: ");
+               xfs_warn(mp, "  type    = 0x%x", lip->li_type);
+               xfs_warn(mp, "  flags   = 0x%x", lip->li_flags);
+               if (!lv)
+                       continue;
+               xfs_warn(mp, "  niovecs = %d", lv->lv_niovecs);
+               xfs_warn(mp, "  size    = %d", lv->lv_size);
+               xfs_warn(mp, "  bytes   = %d", lv->lv_bytes);
+               xfs_warn(mp, "  buf len = %d", lv->lv_buf_len);
+
+               /* dump each iovec for the log item */
+               vec = lv->lv_iovecp;
+               for (i = 0; i < lv->lv_niovecs; i++) {
+                       int dumplen = min(vec->i_len, 32);
+
+                       xfs_warn(mp, "  iovec[%d]", i);
+                       xfs_warn(mp, "    type  = 0x%x", vec->i_type);
+                       xfs_warn(mp, "    len   = %d", vec->i_len);
+                       xfs_warn(mp, "    first %d bytes of iovec[%d]:", dumplen, i);
+                       xfs_hex_dump(vec->i_addr, dumplen);;
+
+                       vec++;
+               }
+       }
+}
+
 /*
  * 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.
index 8de3baa7d3f0f8b1c2bc1adc588c5b894faf745f..04b389210cc723a7514a9cc6ba3d17f82e19c222 100644 (file)
@@ -459,6 +459,21 @@ xlog_cil_insert_items(
        tp->t_ticket->t_curr_res -= len;
        ctx->space_used += len;
 
+       /*
+        * If we've overrun the reservation, dump the tx details before we move
+        * the log items. Shutdown is imminent...
+        */
+       if (WARN_ON(tp->t_ticket->t_curr_res < 0)) {
+               xfs_warn(log->l_mp, "Transaction log reservation overrun:");
+               xfs_warn(log->l_mp,
+                        "  log items: %d bytes (iov hdrs: %d bytes)",
+                        len, iovhdr_res);
+               xfs_warn(log->l_mp, "  split region headers: %d bytes",
+                        split_res);
+               xfs_warn(log->l_mp, "  ctx ticket: %d bytes", ctx_res);
+               xlog_print_trans(tp);
+       }
+
        /*
         * Now (re-)position everything modified at the tail of the CIL.
         * We do this here so we only need to take the CIL lock once during
@@ -481,6 +496,9 @@ xlog_cil_insert_items(
        }
 
        spin_unlock(&cil->xc_cil_lock);
+
+       if (tp->t_ticket->t_curr_res < 0)
+               xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
 }
 
 static void
@@ -988,12 +1006,6 @@ xfs_log_commit_cil(
 
        xlog_cil_insert_items(log, tp);
 
-       /* check we didn't blow the reservation */
-       if (tp->t_ticket->t_curr_res < 0) {
-               xlog_print_tic_res(mp, tp->t_ticket);
-               xfs_force_shutdown(log->l_mp, SHUTDOWN_LOG_IO_ERROR);
-       }
-
        tp->t_commit_lsn = cil->xc_ctx->sequence;
        if (commit_lsn)
                *commit_lsn = tp->t_commit_lsn;
index c2604a5366f274cc5d1268a633a5885a05fd0446..62113a5d2504452df40bb55c0e01ab713a28e9af 100644 (file)
@@ -456,6 +456,7 @@ 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,