Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 371052
b: refs/heads/master
c: 666d644
h: refs/heads/master
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed Apr 5, 2013
1 parent 2c31534 commit 439d999
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3d6e036193bfa67a8a1cc1908fe910c7a014d183
refs/heads/master: 666d644cd72a9ec58b353209ff191d7430f3b357
27 changes: 13 additions & 14 deletions trunk/fs/xfs/xfs_extfree_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,16 @@ xfs_efi_item_free(
* 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.
* 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 (!test_and_clear_bit(XFS_EFI_COMMITTED, &efip->efi_flags)) {
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,
Expand Down Expand Up @@ -126,8 +125,8 @@ xfs_efi_item_pin(
* 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.
* transaction and free it. Otherwise coordinate with xfs_efi_release()
* to determine who gets to free the EFI.
*/
STATIC void
xfs_efi_item_unpin(
Expand Down Expand Up @@ -171,19 +170,13 @@ xfs_efi_item_unlock(

/*
* The EFI is logged only once and cannot be moved in the log, so simply return
* the lsn at which it's been logged. For bulk transaction committed
* processing, the EFI may be processed but not yet unpinned prior to the EFD
* being processed. Set the XFS_EFI_COMMITTED flag so this case can be detected
* when processing the EFD.
* the lsn at which it's been logged.
*/
STATIC xfs_lsn_t
xfs_efi_item_committed(
struct xfs_log_item *lip,
xfs_lsn_t lsn)
{
struct xfs_efi_log_item *efip = EFI_ITEM(lip);

set_bit(XFS_EFI_COMMITTED, &efip->efi_flags);
return lsn;
}

Expand Down Expand Up @@ -241,6 +234,7 @@ xfs_efi_init(
efip->efi_format.efi_nextents = nextents;
efip->efi_format.efi_id = (__psint_t)(void*)efip;
atomic_set(&efip->efi_next_extent, 0);
atomic_set(&efip->efi_refcount, 2);

return efip;
}
Expand Down Expand Up @@ -310,8 +304,13 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
uint nextents)
{
ASSERT(atomic_read(&efip->efi_next_extent) >= nextents);
if (atomic_sub_and_test(nextents, &efip->efi_next_extent))
if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) {
__xfs_efi_release(efip);

/* recovery needs us to drop the EFI reference, too */
if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags))
__xfs_efi_release(efip);
}
}

static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)
Expand Down
14 changes: 9 additions & 5 deletions trunk/fs/xfs/xfs_extfree_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,20 @@ typedef struct xfs_efd_log_format_64 {
* Define EFI flag bits. Manipulated by set/clear/test_bit operators.
*/
#define XFS_EFI_RECOVERED 1
#define XFS_EFI_COMMITTED 2

/*
* This is the "extent free intention" log item. It is used
* to log the fact that some extents need to be free. It is
* used in conjunction with the "extent free done" log item
* described below.
* This is the "extent free intention" log item. It is used to log the fact
* that some extents need to be free. It is used in conjunction with the
* "extent free done" log item described below.
*
* The EFI is reference counted so that it is not freed prior to both the EFI
* and EFD being committed and unpinned. This ensures that when the last
* reference goes away the EFI will always be in the AIL as it has been
* unpinned, regardless of whether the EFD is processed before or after the EFI.
*/
typedef struct xfs_efi_log_item {
xfs_log_item_t efi_item;
atomic_t efi_refcount;
atomic_t efi_next_extent;
unsigned long efi_flags; /* misc flags */
xfs_efi_log_format_t efi_format;
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -2948,6 +2948,7 @@ xlog_recover_process_efi(
* This will pull the EFI from the AIL and
* free the memory associated with it.
*/
set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
xfs_efi_release(efip, efip->efi_format.efi_nextents);
return XFS_ERROR(EIO);
}
Expand Down

0 comments on commit 439d999

Please sign in to comment.