Skip to content

Commit

Permalink
xfs: simplify log item descriptor tracking
Browse files Browse the repository at this point in the history
Currently we track log item descriptor belonging to a transaction using a
complex opencoded chunk allocator.  This code has been there since day one
and seems to work around the lack of an efficient slab allocator.

This patch replaces it with dynamically allocated log item descriptors
from a dedicated slab pool, linked to the transaction by a linked list.

This allows to greatly simplify the log item descriptor tracking to the
point where it's just a couple hundred lines in xfs_trans.c instead of
a separate file.  The external API has also been simplified while we're
at it - the xfs_trans_add_item and xfs_trans_del_item functions to add/
delete items from a transaction have been simplified to the bare minium,
and the xfs_trans_find_item function is replaced with a direct dereference
of the li_desc field.  All debug code walking the list of log items in
a transaction is down to a simple list_for_each_entry.

Note that we could easily use a singly linked list here instead of the
double linked list from list.h as the fastpath only does deletion from
sequential traversal.  But given that we don't have one available as
a library function yet I use the list.h functions for simplicity.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
  • Loading branch information
Christoph Hellwig authored and Alex Elder committed Jul 26, 2010
1 parent 3400777 commit e98c414
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 759 deletions.
1 change: 0 additions & 1 deletion fs/xfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ xfs-y += xfs_alloc.o \
xfs_trans_buf.o \
xfs_trans_extfree.o \
xfs_trans_inode.o \
xfs_trans_item.o \
xfs_utils.o \
xfs_vnodeops.o \
xfs_rw.o
Expand Down
11 changes: 10 additions & 1 deletion fs/xfs/linux-2.6/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,12 @@ xfs_init_zones(void)
if (!xfs_trans_zone)
goto out_destroy_ifork_zone;

xfs_log_item_desc_zone =
kmem_zone_init(sizeof(struct xfs_log_item_desc),
"xfs_log_item_desc");
if (!xfs_log_item_desc_zone)
goto out_destroy_trans_zone;

/*
* The size of the zone allocated buf log item is the maximum
* size possible under XFS. This wastes a little bit of memory,
Expand All @@ -1712,7 +1718,7 @@ xfs_init_zones(void)
(((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) /
NBWORD) * sizeof(int))), "xfs_buf_item");
if (!xfs_buf_item_zone)
goto out_destroy_trans_zone;
goto out_destroy_log_item_desc_zone;

xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) +
((XFS_EFD_MAX_FAST_EXTENTS - 1) *
Expand Down Expand Up @@ -1749,6 +1755,8 @@ xfs_init_zones(void)
kmem_zone_destroy(xfs_efd_zone);
out_destroy_buf_item_zone:
kmem_zone_destroy(xfs_buf_item_zone);
out_destroy_log_item_desc_zone:
kmem_zone_destroy(xfs_log_item_desc_zone);
out_destroy_trans_zone:
kmem_zone_destroy(xfs_trans_zone);
out_destroy_ifork_zone:
Expand Down Expand Up @@ -1779,6 +1787,7 @@ xfs_destroy_zones(void)
kmem_zone_destroy(xfs_efi_zone);
kmem_zone_destroy(xfs_efd_zone);
kmem_zone_destroy(xfs_buf_item_zone);
kmem_zone_destroy(xfs_log_item_desc_zone);
kmem_zone_destroy(xfs_trans_zone);
kmem_zone_destroy(xfs_ifork_zone);
kmem_zone_destroy(xfs_dabuf_zone);
Expand Down
25 changes: 6 additions & 19 deletions fs/xfs/quota/xfs_trans_dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,14 @@ xfs_trans_dqjoin(
xfs_trans_t *tp,
xfs_dquot_t *dqp)
{
xfs_dq_logitem_t *lp = &dqp->q_logitem;

ASSERT(dqp->q_transp != tp);
ASSERT(XFS_DQ_IS_LOCKED(dqp));
ASSERT(lp->qli_dquot == dqp);
ASSERT(dqp->q_logitem.qli_dquot == dqp);

/*
* Get a log_item_desc to point at the new item.
*/
(void) xfs_trans_add_item(tp, (xfs_log_item_t*)(lp));
xfs_trans_add_item(tp, &dqp->q_logitem.qli_item);

/*
* Initialize i_transp so we can later determine if this dquot is
Expand All @@ -83,16 +81,11 @@ xfs_trans_log_dquot(
xfs_trans_t *tp,
xfs_dquot_t *dqp)
{
xfs_log_item_desc_t *lidp;

ASSERT(dqp->q_transp == tp);
ASSERT(XFS_DQ_IS_LOCKED(dqp));

lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(&dqp->q_logitem));
ASSERT(lidp != NULL);

tp->t_flags |= XFS_TRANS_DIRTY;
lidp->lid_flags |= XFS_LID_DIRTY;
dqp->q_logitem.qli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
}

/*
Expand Down Expand Up @@ -864,9 +857,8 @@ xfs_trans_get_qoff_item(
/*
* Get a log_item_desc to point at the new item.
*/
(void) xfs_trans_add_item(tp, (xfs_log_item_t*)q);

return (q);
xfs_trans_add_item(tp, &q->qql_item);
return q;
}


Expand All @@ -880,13 +872,8 @@ xfs_trans_log_quotaoff_item(
xfs_trans_t *tp,
xfs_qoff_logitem_t *qlp)
{
xfs_log_item_desc_t *lidp;

lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)qlp);
ASSERT(lidp != NULL);

tp->t_flags |= XFS_TRANS_DIRTY;
lidp->lid_flags |= XFS_LID_DIRTY;
qlp->qql_item.li_desc->lid_flags |= XFS_LID_DIRTY;
}

STATIC void
Expand Down
45 changes: 10 additions & 35 deletions fs/xfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -5857,43 +5857,18 @@ xfs_bmap_get_bp(
bp = NULL;

if (!bp) { /* Chase down all the log items to see if the bp is there */
xfs_log_item_chunk_t *licp;
xfs_trans_t *tp;

tp = cur->bc_tp;
licp = &tp->t_items;
while (!bp && licp != NULL) {
if (xfs_lic_are_all_free(licp)) {
licp = licp->lic_next;
continue;
}
for (i = 0; i < licp->lic_unused; i++) {
xfs_log_item_desc_t *lidp;
xfs_log_item_t *lip;
xfs_buf_log_item_t *bip;
xfs_buf_t *lbp;

if (xfs_lic_isfree(licp, i)) {
continue;
}

lidp = xfs_lic_slot(licp, i);
lip = lidp->lid_item;
if (lip->li_type != XFS_LI_BUF)
continue;

bip = (xfs_buf_log_item_t *)lip;
lbp = bip->bli_buf;

if (XFS_BUF_ADDR(lbp) == bno) {
bp = lbp;
break; /* Found it */
}
}
licp = licp->lic_next;
struct xfs_log_item_desc *lidp;
struct xfs_buf_log_item *bip;

list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) {
bip = (struct xfs_buf_log_item *)lidp->lid_item;
if (bip->bli_item.li_type == XFS_LI_BUF &&
XFS_BUF_ADDR(bip->bli_buf) == bno)
return bip->bli_buf;
}
}
return(bp);

return bp;
}

STATIC void
Expand Down
5 changes: 1 addition & 4 deletions fs/xfs/xfs_buf_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,10 @@ xfs_buf_item_unpin_remove(
* occurs later in the xfs_trans_uncommit() will try to
* reference the buffer which we no longer have a hold on.
*/
struct xfs_log_item_desc *lidp;

ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0);
trace_xfs_buf_item_unpin_stale(bip);

lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)bip);
xfs_trans_free_item(tp, lidp);
xfs_trans_del_item(&bip->bli_item);

/*
* Since the transaction no longer refers to the buffer, the
Expand Down
8 changes: 4 additions & 4 deletions fs/xfs/xfs_extfree_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,18 @@ 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) {
struct xfs_log_item *lip = &efip->efi_item;

/*
* 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_del_item(lip);

/* xfs_trans_ail_delete() drops the AIL lock. */
xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip);
xfs_trans_ail_delete(ailp, lip);
xfs_efi_item_free(efip);
} else {
efip->efi_flags |= XFS_EFI_COMMITTED;
Expand Down
Loading

0 comments on commit e98c414

Please sign in to comment.