/*ARGSUSED*/ STATIC void xfs_efi_item_unlock(xfs_efi_log_item_t *efip) { if (efip->efi_item.li_flags & XFS_LI_ABORTED) xfs_efi_item_free(efip); return; }
/* * Efi items have no locking, so just return. */ STATIC void xfs_efi_item_unlock( struct xfs_log_item *lip) { if (lip->li_flags & XFS_LI_ABORTED) xfs_efi_item_free(EFI_ITEM(lip)); }
/* * This is called by the efd item code below to release references to * the given efi item. Each efd calls this with the number of * extents that it has logged, and when the sum of these reaches * the total number of extents logged by this efi item we can free * the efi item. * * Freeing the efi item requires that we remove it from the AIL. * We'll use the AIL lock to protect our counters as well as * the removal from the AIL. */ void xfs_efi_release(xfs_efi_log_item_t *efip, uint nextents) { xfs_mount_t *mp; int extents_left; SPLDECL(s); mp = efip->efi_item.li_mountp; ASSERT(efip->efi_next_extent > 0); ASSERT(efip->efi_flags & XFS_EFI_COMMITTED); AIL_LOCK(mp, s); ASSERT(efip->efi_next_extent >= nextents); efip->efi_next_extent -= nextents; extents_left = efip->efi_next_extent; if (extents_left == 0) { /* * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); xfs_efi_item_free(efip); } else { AIL_UNLOCK(mp, s); } }
/* * like unpin only we have to also clear the xaction descriptor * pointing the log item if we free the item. This routine duplicates * unpin because efi_flags is protected by the AIL lock. Freeing * the descriptor and then calling unpin would force us to drop the AIL * lock which would open up a race condition. */ STATIC void xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) { xfs_mount_t *mp; xfs_log_item_desc_t *lidp; SPLDECL(s); mp = efip->efi_item.li_mountp; AIL_LOCK(mp, s); if (efip->efi_flags & XFS_EFI_CANCELED) { /* * free the xaction descriptor pointing to this item */ lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip); xfs_trans_free_item(tp, lidp); /* * pull the item off the AIL. * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; AIL_UNLOCK(mp, s); } }
/* * Freeing the efi requires that we remove it from the AIL if it has already * been placed there. However, the EFI may not yet have been placed in the AIL * when called by xfs_efi_release() from EFD processing due to the ordering of * committed vs unpin operations in bulk insert operations. Hence the * test_and_clear_bit(XFS_EFI_COMMITTED) to ensure only the last caller frees * the EFI. */ STATIC void __xfs_efi_release( struct xfs_efi_log_item *efip) { struct xfs_ail *ailp = efip->efi_item.li_ailp; if (!test_and_clear_bit(XFS_EFI_COMMITTED, &efip->efi_flags)) { spin_lock(&ailp->xa_lock); /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, &efip->efi_item); xfs_efi_item_free(efip); } }
/* * Freeing the efi requires that we remove it from the AIL if it has already * been placed there. However, the EFI may not yet have been placed in the AIL * when called by xfs_efi_release() from EFD processing due to the ordering of * committed vs unpin operations in bulk insert operations. Hence the reference * count to ensure only the last caller frees the EFI. */ STATIC void __xfs_efi_release( struct xfs_efi_log_item *efip) { struct xfs_ail *ailp = efip->efi_item.li_ailp; if (atomic_dec_and_test(&efip->efi_refcount)) { spin_lock(&ailp->xa_lock); /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, &efip->efi_item, SHUTDOWN_LOG_IO_ERROR); xfs_efi_item_free(efip); } }
/*ARGSUSED*/ STATIC void xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale) { struct xfs_ail *ailp = efip->efi_item.li_ailp; spin_lock(&ailp->xa_lock); if (efip->efi_flags & XFS_EFI_CANCELED) { /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; spin_unlock(&ailp->xa_lock); } }
/* * While EFIs cannot really be pinned, the unpin operation is the last place at * which the EFI is manipulated during a transaction. If we are being asked to * remove the EFI it's because the transaction has been cancelled and by * definition that means the EFI cannot be in the AIL so remove it from the * transaction and free it. Otherwise coordinate with xfs_efi_release() (via * XFS_EFI_COMMITTED) to determine who gets to free the EFI. */ STATIC void xfs_efi_item_unpin( struct xfs_log_item *lip, int remove) { struct xfs_efi_log_item *efip = EFI_ITEM(lip); if (remove) { ASSERT(!(lip->li_flags & XFS_LI_IN_AIL)); xfs_trans_del_item(lip); xfs_efi_item_free(efip); return; } __xfs_efi_release(efip); }
/*ARGSUSED*/ STATIC void xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale) { xfs_mount_t *mp; mp = efip->efi_item.li_mountp; spin_lock(&mp->m_ail_lock); if (efip->efi_flags & XFS_EFI_CANCELED) { /* * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; spin_unlock(&mp->m_ail_lock); } }
/*ARGSUSED*/ STATIC void xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale) { xfs_mount_t *mp; SPLDECL(s); mp = efip->efi_item.li_mountp; AIL_LOCK(mp, s); if (efip->efi_flags & XFS_EFI_CANCELED) { /* * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; AIL_UNLOCK(mp, s); } }
/* * While EFIs cannot really be pinned, the unpin operation is the * last place at which the EFI is manipulated during a transaction. * Here we coordinate with xfs_efi_cancel() to determine who gets to * free the EFI. */ STATIC void xfs_efi_item_unpin( struct xfs_log_item *lip, int remove) { struct xfs_efi_log_item *efip = EFI_ITEM(lip); struct xfs_ail *ailp = lip->li_ailp; spin_lock(&ailp->xa_lock); if (efip->efi_flags & XFS_EFI_CANCELED) { if (remove) xfs_trans_del_item(lip); /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, lip); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; spin_unlock(&ailp->xa_lock); } }
/* * This is called by the efd item code below to release references to * the given efi item. Each efd calls this with the number of * extents that it has logged, and when the sum of these reaches * the total number of extents logged by this efi item we can free * the efi item. * * Freeing the efi item requires that we remove it from the AIL. * We'll use the AIL lock to protect our counters as well as * the removal from the AIL. */ void xfs_efi_release(xfs_efi_log_item_t *efip, uint nextents) { struct xfs_ail *ailp = efip->efi_item.li_ailp; int extents_left; ASSERT(efip->efi_next_extent > 0); ASSERT(efip->efi_flags & XFS_EFI_COMMITTED); spin_lock(&ailp->xa_lock); ASSERT(efip->efi_next_extent >= nextents); efip->efi_next_extent -= nextents; extents_left = efip->efi_next_extent; if (extents_left == 0) { /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); xfs_efi_item_free(efip); } else { spin_unlock(&ailp->xa_lock); } }
/* * like unpin only we have to also clear the xaction descriptor * pointing the log item if we free the item. This routine duplicates * unpin because efi_flags is protected by the AIL lock. Freeing * the descriptor and then calling unpin would force us to drop the AIL * lock which would open up a race condition. */ STATIC void xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) { struct xfs_ail *ailp = efip->efi_item.li_ailp; xfs_log_item_desc_t *lidp; spin_lock(&ailp->xa_lock); if (efip->efi_flags & XFS_EFI_CANCELED) { /* * free the xaction descriptor pointing to this item */ lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip); xfs_trans_free_item(tp, lidp); /* xfs_trans_ail_delete() drops the AIL lock. */ xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); xfs_efi_item_free(efip); } else { efip->efi_flags |= XFS_EFI_COMMITTED; spin_unlock(&ailp->xa_lock); } }
/* * This is called when the transaction logging the EFI is aborted. * Free up the EFI and return. No need to clean up the slot for * the item in the transaction. That was done by the unpin code * which is called prior to this routine in the abort/fs-shutdown path. */ STATIC void xfs_efi_item_abort(xfs_efi_log_item_t *efip) { xfs_efi_item_free(efip); }