|
@@ -410,6 +410,7 @@ xlog_cil_insert_items(
|
|
|
int len = 0;
|
|
int len = 0;
|
|
|
int diff_iovecs = 0;
|
|
int diff_iovecs = 0;
|
|
|
int iclog_space;
|
|
int iclog_space;
|
|
|
|
|
+ int iovhdr_res = 0, split_res = 0, ctx_res = 0;
|
|
|
|
|
|
|
|
ASSERT(tp);
|
|
ASSERT(tp);
|
|
|
|
|
|
|
@@ -419,30 +420,11 @@ xlog_cil_insert_items(
|
|
|
*/
|
|
*/
|
|
|
xlog_cil_insert_format_items(log, tp, &len, &diff_iovecs);
|
|
xlog_cil_insert_format_items(log, tp, &len, &diff_iovecs);
|
|
|
|
|
|
|
|
- /*
|
|
|
|
|
- * 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
|
|
|
|
|
- * the transaction commit.
|
|
|
|
|
- */
|
|
|
|
|
spin_lock(&cil->xc_cil_lock);
|
|
spin_lock(&cil->xc_cil_lock);
|
|
|
- list_for_each_entry(lidp, &tp->t_items, lid_trans) {
|
|
|
|
|
- struct xfs_log_item *lip = lidp->lid_item;
|
|
|
|
|
-
|
|
|
|
|
- /* Skip items which aren't dirty in this transaction. */
|
|
|
|
|
- if (!(lidp->lid_flags & XFS_LID_DIRTY))
|
|
|
|
|
- continue;
|
|
|
|
|
-
|
|
|
|
|
- /*
|
|
|
|
|
- * Only move the item if it isn't already at the tail. This is
|
|
|
|
|
- * to prevent a transient list_empty() state when reinserting
|
|
|
|
|
- * an item that is already the only item in the CIL.
|
|
|
|
|
- */
|
|
|
|
|
- if (!list_is_last(&lip->li_cil, &cil->xc_cil))
|
|
|
|
|
- list_move_tail(&lip->li_cil, &cil->xc_cil);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
/* account for space used by new iovec headers */
|
|
/* account for space used by new iovec headers */
|
|
|
- len += diff_iovecs * sizeof(xlog_op_header_t);
|
|
|
|
|
|
|
+ iovhdr_res = diff_iovecs * sizeof(xlog_op_header_t);
|
|
|
|
|
+ len += iovhdr_res;
|
|
|
ctx->nvecs += diff_iovecs;
|
|
ctx->nvecs += diff_iovecs;
|
|
|
|
|
|
|
|
/* attach the transaction to the CIL if it has any busy extents */
|
|
/* attach the transaction to the CIL if it has any busy extents */
|
|
@@ -457,27 +439,47 @@ xlog_cil_insert_items(
|
|
|
* during the transaction commit.
|
|
* during the transaction commit.
|
|
|
*/
|
|
*/
|
|
|
if (ctx->ticket->t_curr_res == 0) {
|
|
if (ctx->ticket->t_curr_res == 0) {
|
|
|
- ctx->ticket->t_curr_res = ctx->ticket->t_unit_res;
|
|
|
|
|
- tp->t_ticket->t_curr_res -= ctx->ticket->t_unit_res;
|
|
|
|
|
|
|
+ ctx_res = ctx->ticket->t_unit_res;
|
|
|
|
|
+ ctx->ticket->t_curr_res = ctx_res;
|
|
|
|
|
+ tp->t_ticket->t_curr_res -= ctx_res;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* do we need space for more log record headers? */
|
|
/* do we need space for more log record headers? */
|
|
|
iclog_space = log->l_iclog_size - log->l_iclog_hsize;
|
|
iclog_space = log->l_iclog_size - log->l_iclog_hsize;
|
|
|
if (len > 0 && (ctx->space_used / iclog_space !=
|
|
if (len > 0 && (ctx->space_used / iclog_space !=
|
|
|
(ctx->space_used + len) / iclog_space)) {
|
|
(ctx->space_used + len) / iclog_space)) {
|
|
|
- int hdrs;
|
|
|
|
|
-
|
|
|
|
|
- hdrs = (len + iclog_space - 1) / iclog_space;
|
|
|
|
|
|
|
+ split_res = (len + iclog_space - 1) / iclog_space;
|
|
|
/* need to take into account split region headers, too */
|
|
/* need to take into account split region headers, too */
|
|
|
- hdrs *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
|
|
|
|
|
- ctx->ticket->t_unit_res += hdrs;
|
|
|
|
|
- ctx->ticket->t_curr_res += hdrs;
|
|
|
|
|
- tp->t_ticket->t_curr_res -= hdrs;
|
|
|
|
|
|
|
+ split_res *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
|
|
|
|
|
+ ctx->ticket->t_unit_res += split_res;
|
|
|
|
|
+ ctx->ticket->t_curr_res += split_res;
|
|
|
|
|
+ tp->t_ticket->t_curr_res -= split_res;
|
|
|
ASSERT(tp->t_ticket->t_curr_res >= len);
|
|
ASSERT(tp->t_ticket->t_curr_res >= len);
|
|
|
}
|
|
}
|
|
|
tp->t_ticket->t_curr_res -= len;
|
|
tp->t_ticket->t_curr_res -= len;
|
|
|
ctx->space_used += len;
|
|
ctx->space_used += len;
|
|
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
|
+ * 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
|
|
|
|
|
+ * the transaction commit.
|
|
|
|
|
+ */
|
|
|
|
|
+ list_for_each_entry(lidp, &tp->t_items, lid_trans) {
|
|
|
|
|
+ struct xfs_log_item *lip = lidp->lid_item;
|
|
|
|
|
+
|
|
|
|
|
+ /* Skip items which aren't dirty in this transaction. */
|
|
|
|
|
+ if (!(lidp->lid_flags & XFS_LID_DIRTY))
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Only move the item if it isn't already at the tail. This is
|
|
|
|
|
+ * to prevent a transient list_empty() state when reinserting
|
|
|
|
|
+ * an item that is already the only item in the CIL.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (!list_is_last(&lip->li_cil, &cil->xc_cil))
|
|
|
|
|
+ list_move_tail(&lip->li_cil, &cil->xc_cil);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
spin_unlock(&cil->xc_cil_lock);
|
|
spin_unlock(&cil->xc_cil_lock);
|
|
|
}
|
|
}
|
|
|
|
|
|