Commit 8e646a55 authored by Dave Chinner's avatar Dave Chinner Committed by Alex Elder

xfs: update and factor xfs_trans_committed()

The function header to xfs-trans_committed has long had this
comment:

 * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item()

To prepare for different methods of committing items, convert the
code to use xfs_trans_next_item() and factor the code into smaller,
more digestible chunks.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent a3ccd2ca
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *);
STATIC void xfs_trans_uncommit(xfs_trans_t *, uint); STATIC void xfs_trans_uncommit(xfs_trans_t *, uint);
STATIC void xfs_trans_committed(xfs_trans_t *, int); STATIC void xfs_trans_committed(xfs_trans_t *, int);
STATIC void xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int);
STATIC void xfs_trans_free(xfs_trans_t *); STATIC void xfs_trans_free(xfs_trans_t *);
kmem_zone_t *xfs_trans_zone; kmem_zone_t *xfs_trans_zone;
...@@ -1301,60 +1300,86 @@ xfs_trans_roll( ...@@ -1301,60 +1300,86 @@ xfs_trans_roll(
} }
/* /*
* THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item(). * The committed item processing consists of calling the committed routine of
* each logged item, updating the item's position in the AIL if necessary, and
* unpinning each item. If the committed routine returns -1, then do nothing
* further with the item because it may have been freed.
* *
* This is typically called by the LM when a transaction has been fully * Since items are unlocked when they are copied to the incore log, it is
* committed to disk. It needs to unpin the items which have * possible for two transactions to be completing and manipulating the same
* been logged by the transaction and update their positions * item simultaneously. The AIL lock will protect the lsn field of each item.
* in the AIL if necessary. * The value of this field can never go backwards.
* This also gets called when the transactions didn't get written out
* because of an I/O error. Abortflag & XFS_LI_ABORTED is set then.
* *
* Call xfs_trans_chunk_committed() to process the items in * We unpin the items after repositioning them in the AIL, because otherwise
* each chunk. * they could be immediately flushed and we'd have to race with the flusher
* trying to pull the item from the AIL as we add it.
*/ */
STATIC void static void
xfs_trans_committed( xfs_trans_item_committed(
xfs_trans_t *tp, xfs_log_item_t *lip,
int abortflag) xfs_lsn_t commit_lsn,
int aborted)
{ {
xfs_log_item_chunk_t *licp; xfs_lsn_t item_lsn;
xfs_log_item_chunk_t *next_licp; struct xfs_ail *ailp;
xfs_log_busy_chunk_t *lbcp;
xfs_log_busy_slot_t *lbsp; if (aborted)
int i; lip->li_flags |= XFS_LI_ABORTED;
/* /*
* Call the transaction's completion callback if there * Send in the ABORTED flag to the COMMITTED routine so that it knows
* is one. * whether the transaction was aborted or not.
*/ */
if (tp->t_callback != NULL) { item_lsn = IOP_COMMITTED(lip, commit_lsn);
tp->t_callback(tp, tp->t_callarg);
}
/* /*
* Special case the chunk embedded in the transaction. * If the committed routine returns -1, item has been freed.
*/ */
licp = &(tp->t_items); if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
if (!(xfs_lic_are_all_free(licp))) { return;
xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
}
/* /*
* Process the items in each chunk in turn. * If the returned lsn is greater than what it contained before, update
* the location of the item in the AIL. If it is not, then do nothing.
* Items can never move backwards in the AIL.
*
* While the new lsn should usually be greater, it is possible that a
* later transaction completing simultaneously with an earlier one
* using the same item could complete first with a higher lsn. This
* would cause the earlier transaction to fail the test below.
*/ */
licp = licp->lic_next; ailp = lip->li_ailp;
while (licp != NULL) { spin_lock(&ailp->xa_lock);
ASSERT(!xfs_lic_are_all_free(licp)); if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); /*
next_licp = licp->lic_next; * This will set the item's lsn to item_lsn and update the
kmem_free(licp); * position of the item in the AIL.
licp = next_licp; *
* xfs_trans_ail_update() drops the AIL lock.
*/
xfs_trans_ail_update(ailp, lip, item_lsn);
} else {
spin_unlock(&ailp->xa_lock);
} }
/* /*
* Clear all the per-AG busy list items listed in this transaction * Now that we've repositioned the item in the AIL, unpin it so it can
* be flushed. Pass information about buffer stale state down from the
* log item flags, if anyone else stales the buffer we do not want to
* pay any attention to it.
*/ */
IOP_UNPIN(lip);
}
/* Clear all the per-AG busy list items listed in this transaction */
static void
xfs_trans_clear_busy_extents(
struct xfs_trans *tp)
{
xfs_log_busy_chunk_t *lbcp;
xfs_log_busy_slot_t *lbsp;
int i;
lbcp = &tp->t_busy; lbcp = &tp->t_busy;
while (lbcp != NULL) { while (lbcp != NULL) {
for (i = 0, lbsp = lbcp->lbc_busy; i < lbcp->lbc_unused; i++, lbsp++) { for (i = 0, lbsp = lbcp->lbc_busy; i < lbcp->lbc_unused; i++, lbsp++) {
...@@ -1366,107 +1391,48 @@ xfs_trans_committed( ...@@ -1366,107 +1391,48 @@ xfs_trans_committed(
lbcp = lbcp->lbc_next; lbcp = lbcp->lbc_next;
} }
xfs_trans_free_busy(tp); xfs_trans_free_busy(tp);
/*
* That's it for the transaction structure. Free it.
*/
xfs_trans_free(tp);
} }
/* /*
* This is called to perform the commit processing for each * This is typically called by the LM when a transaction has been fully
* item described by the given chunk. * committed to disk. It needs to unpin the items which have
* * been logged by the transaction and update their positions
* The commit processing consists of unlocking items which were * in the AIL if necessary.
* held locked with the SYNC_UNLOCK attribute, calling the committed
* routine of each logged item, updating the item's position in the AIL
* if necessary, and unpinning each item. If the committed routine
* returns -1, then do nothing further with the item because it
* may have been freed.
*
* Since items are unlocked when they are copied to the incore
* log, it is possible for two transactions to be completing
* and manipulating the same item simultaneously. The AIL lock
* will protect the lsn field of each item. The value of this
* field can never go backwards.
* *
* We unpin the items after repositioning them in the AIL, because * This also gets called when the transactions didn't get written out
* otherwise they could be immediately flushed and we'd have to race * because of an I/O error. Abortflag & XFS_LI_ABORTED is set then.
* with the flusher trying to pull the item from the AIL as we add it.
*/ */
STATIC void STATIC void
xfs_trans_chunk_committed( xfs_trans_committed(
xfs_log_item_chunk_t *licp, xfs_trans_t *tp,
xfs_lsn_t lsn, int abortflag)
int aborted)
{ {
xfs_log_item_desc_t *lidp; xfs_log_item_desc_t *lidp;
xfs_log_item_t *lip; xfs_log_item_chunk_t *licp;
xfs_lsn_t item_lsn; xfs_log_item_chunk_t *next_licp;
int i;
lidp = licp->lic_descs;
for (i = 0; i < licp->lic_unused; i++, lidp++) {
struct xfs_ail *ailp;
if (xfs_lic_isfree(licp, i)) {
continue;
}
lip = lidp->lid_item;
if (aborted)
lip->li_flags |= XFS_LI_ABORTED;
/*
* Send in the ABORTED flag to the COMMITTED routine
* so that it knows whether the transaction was aborted
* or not.
*/
item_lsn = IOP_COMMITTED(lip, lsn);
/* /*
* If the committed routine returns -1, make * Call the transaction's completion callback if there
* no more references to the item. * is one.
*/ */
if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) { if (tp->t_callback != NULL) {
continue; tp->t_callback(tp, tp->t_callarg);
} }
/* for (lidp = xfs_trans_first_item(tp);
* If the returned lsn is greater than what it lidp != NULL;
* contained before, update the location of the lidp = xfs_trans_next_item(tp, lidp)) {
* item in the AIL. If it is not, then do nothing. xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
* Items can never move backwards in the AIL. }
*
* While the new lsn should usually be greater, it
* is possible that a later transaction completing
* simultaneously with an earlier one using the
* same item could complete first with a higher lsn.
* This would cause the earlier transaction to fail
* the test below.
*/
ailp = lip->li_ailp;
spin_lock(&ailp->xa_lock);
if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
/*
* This will set the item's lsn to item_lsn
* and update the position of the item in
* the AIL.
*
* xfs_trans_ail_update() drops the AIL lock.
*/
xfs_trans_ail_update(ailp, lip, item_lsn);
} else {
spin_unlock(&ailp->xa_lock);
}
/* /* free the item chunks, ignoring the embedded chunk */
* Now that we've repositioned the item in the AIL, licp = tp->t_items.lic_next;
* unpin it so it can be flushed. Pass information while (licp != NULL) {
* about buffer stale state down from the log item next_licp = licp->lic_next;
* flags, if anyone else stales the buffer we do not kmem_free(licp);
* want to pay any attention to it. licp = next_licp;
*/
IOP_UNPIN(lip);
} }
xfs_trans_clear_busy_extents(tp);
xfs_trans_free(tp);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment