diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index b55abde6c142..940e5bb9786c 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -983,6 +983,9 @@ xfs_log_item_init(
 	item->li_type = type;
 	item->li_ops = ops;
 	item->li_lv = NULL;
+#ifdef DEBUG
+	atomic64_set(&item->li_relog_res, 0);
+#endif
 
 	INIT_LIST_HEAD(&item->li_ail);
 	INIT_LIST_HEAD(&item->li_cil);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index cfa9915523e1..ba2540d8a6c9 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -20,6 +20,7 @@
 #include "xfs_trace.h"
 #include "xfs_error.h"
 #include "xfs_defer.h"
+#include "xfs_log_priv.h"
 
 kmem_zone_t	*xfs_trans_zone;
 
@@ -657,9 +658,19 @@ xfs_trans_relog_item(
 	struct xfs_trans	*tp,
 	struct xfs_log_item	*lip)
 {
+	int			nbytes;
+
+	ASSERT(tp->t_flags & XFS_TRANS_RELOG);
+
 	if (test_and_set_bit(XFS_LI_RELOG, &lip->li_flags))
 		return;
 	trace_xfs_relog_item(lip);
+
+	nbytes = xfs_relog_calc_res(lip);
+
+	tp->t_ticket->t_curr_res -= nbytes;
+	xfs_relog_res_account(lip, nbytes);
+	tp->t_flags |= XFS_TRANS_DIRTY;
 }
 
 void
@@ -667,9 +678,18 @@ xfs_trans_relog_item_cancel(
 	struct xfs_trans	*tp,
 	struct xfs_log_item	*lip)
 {
+	int			res;
+
 	if (!test_and_clear_bit(XFS_LI_RELOG, &lip->li_flags))
 		return;
 	trace_xfs_relog_item_cancel(lip);
+
+	res = xfs_relog_calc_res(lip);
+	if (tp)
+		tp->t_ticket->t_curr_res += res;
+	else
+		xfs_log_ungrant_bytes(lip->li_mountp, res);
+	xfs_relog_res_account(lip, -res);
 }
 
 /* Detach and unlock all of the items in a transaction */
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 6349e78af002..70373e2b8f6d 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -48,6 +48,9 @@ struct xfs_log_item {
 	struct xfs_log_vec		*li_lv;		/* active log vector */
 	struct xfs_log_vec		*li_lv_shadow;	/* standby vector */
 	xfs_lsn_t			li_seq;		/* CIL commit seq */
+#ifdef DEBUG
+	atomic64_t			li_relog_res;	/* automatic relog log res */
+#endif
 };
 
 /*
@@ -216,6 +219,34 @@ xfs_trans_read_buf(
 				      flags, bpp, ops);
 }
 
+/*
+ * Calculate the log reservation required to enable relogging of a log item.
+ */
+static inline int
+xfs_relog_calc_res(
+	struct xfs_log_item	*lip)
+{
+	int			niovecs = 0;
+	int			nbytes = 0;
+
+	/*
+	 * The reservation consumed by a transaction at commit time consists of
+	 * the total size of the formatted log vectors of the items dirtied by
+	 * the transaction, an op header for each iovec in the log vectors, the
+	 * unit reservation of the CIL context ticket, and extra iclog and op
+	 * headers if the CIL context spans multiple iclogs (i.e. split
+	 * reservation). The CIL ticket and split reservation are included by
+	 * xfs_log_calc_unit_res().
+	 */
+	lip->li_ops->iop_size(lip, &niovecs, &nbytes);
+	ASSERT(niovecs == 1);
+
+	nbytes += niovecs * sizeof(xlog_op_header_t);
+	nbytes = xfs_log_calc_unit_res(lip->li_mountp, nbytes);
+
+	return nbytes;
+}
+
 struct xfs_buf	*xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *);
 
 void		xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index ac5019361a13..5c862821171f 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -894,6 +894,7 @@ xfs_trans_ail_init(
 	spin_lock_init(&ailp->ail_lock);
 	INIT_LIST_HEAD(&ailp->ail_buf_list);
 	init_waitqueue_head(&ailp->ail_empty);
+	atomic64_set(&ailp->ail_relog_res, 0);
 
 	ailp->ail_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
 			ailp->ail_mount->m_super->s_id);
@@ -914,6 +915,7 @@ xfs_trans_ail_destroy(
 {
 	struct xfs_ail	*ailp = mp->m_ail;
 
+	ASSERT(atomic64_read(&ailp->ail_relog_res) == 0);
 	kthread_stop(ailp->ail_task);
 	kmem_free(ailp);
 }
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 64965a861346..d923e79676af 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -63,6 +63,7 @@ struct xfs_ail {
 	int			ail_log_flush;
 	struct list_head	ail_buf_list;
 	wait_queue_head_t	ail_empty;
+	atomic64_t		ail_relog_res;
 };
 
 /*
@@ -169,4 +170,17 @@ xfs_set_li_failed(
 	}
 }
 
+static inline int64_t
+xfs_relog_res_account(
+	struct xfs_log_item	*lip,
+	int64_t			bytes)
+{
+#ifdef DEBUG
+	int64_t			res;
+
+	res = atomic64_add_return(bytes, &lip->li_relog_res);
+	ASSERT(res == bytes || (bytes < 0 && res == 0));
+#endif
+	return atomic64_add_return(bytes, &lip->li_ailp->ail_relog_res);
+}
 #endif	/* __XFS_TRANS_PRIV_H__ */
