Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: disentagle EFI release from the extent count

Release of the EFI either occurs based on the reference count or the
extent count. The extent count used is either the count tracked in
the EFI or EFD, depending on the particular situation. In either
case, the count is initialized to the final value and thus always
matches the current efi_next_extent value once the EFI is completely
constructed. For example, the EFI extent count is increased as the
extents are logged in xfs_bmap_finish() and the full free list is
always completely processed. Therefore, the count is guaranteed to
be complete once the EFI transaction is committed. The EFD uses the
efd_nextents counter to release the EFI. This counter is initialized
to the count of the EFI when the EFD is created. Thus the EFD, as
currently used, has no concept of partial EFI release based on
extent count.

Given that the EFI extent count is always released in whole, use of
the extent count for reference counting is unnecessary. Remove this
level of the API and release the EFI based on the core reference
count. The efi_next_extent counter remains because it is still used
to track the slot to log the next extent to free.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>

authored by

Brian Foster and committed by
Dave Chinner
5e4b5386 bc0195aa

+11 -14
+9 -12
fs/xfs/xfs_extfree_item.c
··· 149 149 xfs_efi_item_free(efip); 150 150 return; 151 151 } 152 - __xfs_efi_release(efip); 152 + xfs_efi_release(efip); 153 153 } 154 154 155 155 /* ··· 307 307 * by this efi item we can free the efi item. 308 308 */ 309 309 void 310 - xfs_efi_release(xfs_efi_log_item_t *efip, 311 - uint nextents) 310 + xfs_efi_release( 311 + struct xfs_efi_log_item *efip) 312 312 { 313 - ASSERT(atomic_read(&efip->efi_next_extent) >= nextents); 314 - if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) { 315 - /* recovery needs us to drop the EFI reference, too */ 316 - if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) 317 - __xfs_efi_release(efip); 318 - 313 + /* recovery needs us to drop the EFI reference, too */ 314 + if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) 319 315 __xfs_efi_release(efip); 320 - /* efip may now have been freed, do not reference it again. */ 321 - } 316 + 317 + __xfs_efi_release(efip); 318 + /* efip may now have been freed, do not reference it again. */ 322 319 } 323 320 324 321 static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip) ··· 439 442 * EFI got unpinned and freed before the EFD got aborted. 440 443 */ 441 444 if (!(lip->li_flags & XFS_LI_ABORTED)) 442 - xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); 445 + xfs_efi_release(efdp->efd_efip); 443 446 444 447 xfs_efd_item_free(efdp); 445 448 return (xfs_lsn_t)-1;
+1
fs/xfs/xfs_extfree_item.h
··· 77 77 int xfs_efi_copy_format(xfs_log_iovec_t *buf, 78 78 xfs_efi_log_format_t *dst_efi_fmt); 79 79 void xfs_efi_item_free(xfs_efi_log_item_t *); 80 + void xfs_efi_release(struct xfs_efi_log_item *); 80 81 81 82 #endif /* __XFS_EXTFREE_ITEM_H__ */
+1 -1
fs/xfs/xfs_log_recover.c
··· 3739 3739 * free the memory associated with it. 3740 3740 */ 3741 3741 set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); 3742 - xfs_efi_release(efip, efip->efi_format.efi_nextents); 3742 + xfs_efi_release(efip); 3743 3743 return -EIO; 3744 3744 } 3745 3745 }
-1
fs/xfs/xfs_trans.h
··· 213 213 void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); 214 214 void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); 215 215 struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); 216 - void xfs_efi_release(struct xfs_efi_log_item *, uint); 217 216 void xfs_trans_log_efi_extent(xfs_trans_t *, 218 217 struct xfs_efi_log_item *, 219 218 xfs_fsblock_t,