|
@@ -424,6 +424,51 @@ struct xfs_cil {
|
|
|
sv_t xc_commit_wait;
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * The amount of log space we should the CIL to aggregate is difficult to size.
|
|
|
+ * Whatever we chose we have to make we can get a reservation for the log space
|
|
|
+ * effectively, that it is large enough to capture sufficient relogging to
|
|
|
+ * reduce log buffer IO significantly, but it is not too large for the log or
|
|
|
+ * induces too much latency when writing out through the iclogs. We track both
|
|
|
+ * space consumed and the number of vectors in the checkpoint context, so we
|
|
|
+ * need to decide which to use for limiting.
|
|
|
+ *
|
|
|
+ * Every log buffer we write out during a push needs a header reserved, which
|
|
|
+ * is at least one sector and more for v2 logs. Hence we need a reservation of
|
|
|
+ * at least 512 bytes per 32k of log space just for the LR headers. That means
|
|
|
+ * 16KB of reservation per megabyte of delayed logging space we will consume,
|
|
|
+ * plus various headers. The number of headers will vary based on the num of
|
|
|
+ * io vectors, so limiting on a specific number of vectors is going to result
|
|
|
+ * in transactions of varying size. IOWs, it is more consistent to track and
|
|
|
+ * limit space consumed in the log rather than by the number of objects being
|
|
|
+ * logged in order to prevent checkpoint ticket overruns.
|
|
|
+ *
|
|
|
+ * Further, use of static reservations through the log grant mechanism is
|
|
|
+ * problematic. It introduces a lot of complexity (e.g. reserve grant vs write
|
|
|
+ * grant) and a significant deadlock potential because regranting write space
|
|
|
+ * can block on log pushes. Hence if we have to regrant log space during a log
|
|
|
+ * push, we can deadlock.
|
|
|
+ *
|
|
|
+ * However, we can avoid this by use of a dynamic "reservation stealing"
|
|
|
+ * technique during transaction commit whereby unused reservation space in the
|
|
|
+ * transaction ticket is transferred to the CIL ctx commit ticket to cover the
|
|
|
+ * space needed by the checkpoint transaction. This means that we never need to
|
|
|
+ * specifically reserve space for the CIL checkpoint transaction, nor do we
|
|
|
+ * need to regrant space once the checkpoint completes. This also means the
|
|
|
+ * checkpoint transaction ticket is specific to the checkpoint context, rather
|
|
|
+ * than the CIL itself.
|
|
|
+ *
|
|
|
+ * With dynamic reservations, we can basically make up arbitrary limits for the
|
|
|
+ * checkpoint size so long as they don't violate any other size rules. Hence
|
|
|
+ * the initial maximum size for the checkpoint transaction will be set to a
|
|
|
+ * quarter of the log or 8MB, which ever is smaller. 8MB is an arbitrary limit
|
|
|
+ * right now based on the latency of writing out a large amount of data through
|
|
|
+ * the circular iclog buffers.
|
|
|
+ */
|
|
|
+
|
|
|
+#define XLOG_CIL_SPACE_LIMIT(log) \
|
|
|
+ (min((log->l_logsize >> 2), (8 * 1024 * 1024)))
|
|
|
+
|
|
|
/*
|
|
|
* The reservation head lsn is not made up of a cycle number and block number.
|
|
|
* Instead, it uses a cycle number and byte number. Logs don't expect to
|