aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-06-23 04:11:15 -0400
committerAlex Elder <aelder@sgi.com>2010-07-26 14:16:34 -0400
commite98c414f9a3134fe7efc56ef8f1d394b54bfd40e (patch)
treeb3d4696cfb4875af39041f9ddcd642bd1cd90a29 /fs/xfs
parent3400777ff03a3cd4fdbc6cb15676fc7e7ceefc00 (diff)
xfs: simplify log item descriptor tracking
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/Makefile1
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c11
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c25
-rw-r--r--fs/xfs/xfs_bmap.c45
-rw-r--r--fs/xfs/xfs_buf_item.c5
-rw-r--r--fs/xfs/xfs_extfree_item.c8
-rw-r--r--fs/xfs/xfs_trans.c200
-rw-r--r--fs/xfs/xfs_trans.h105
-rw-r--r--fs/xfs/xfs_trans_buf.c64
-rw-r--r--fs/xfs/xfs_trans_extfree.c22
-rw-r--r--fs/xfs/xfs_trans_inode.c9
-rw-r--r--fs/xfs/xfs_trans_item.c440
-rw-r--r--fs/xfs/xfs_trans_priv.h18
13 files changed, 194 insertions, 759 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index a5239b1713be..0dce969d6cad 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -87,7 +87,6 @@ xfs-y += xfs_alloc.o \
87 xfs_trans_buf.o \ 87 xfs_trans_buf.o \
88 xfs_trans_extfree.o \ 88 xfs_trans_extfree.o \
89 xfs_trans_inode.o \ 89 xfs_trans_inode.o \
90 xfs_trans_item.o \
91 xfs_utils.o \ 90 xfs_utils.o \
92 xfs_vnodeops.o \ 91 xfs_vnodeops.o \
93 xfs_rw.o 92 xfs_rw.o
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 5593066d497d..4b90e4b531b7 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1703,6 +1703,12 @@ xfs_init_zones(void)
1703 if (!xfs_trans_zone) 1703 if (!xfs_trans_zone)
1704 goto out_destroy_ifork_zone; 1704 goto out_destroy_ifork_zone;
1705 1705
1706 xfs_log_item_desc_zone =
1707 kmem_zone_init(sizeof(struct xfs_log_item_desc),
1708 "xfs_log_item_desc");
1709 if (!xfs_log_item_desc_zone)
1710 goto out_destroy_trans_zone;
1711
1706 /* 1712 /*
1707 * The size of the zone allocated buf log item is the maximum 1713 * The size of the zone allocated buf log item is the maximum
1708 * size possible under XFS. This wastes a little bit of memory, 1714 * size possible under XFS. This wastes a little bit of memory,
@@ -1712,7 +1718,7 @@ xfs_init_zones(void)
1712 (((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / 1718 (((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) /
1713 NBWORD) * sizeof(int))), "xfs_buf_item"); 1719 NBWORD) * sizeof(int))), "xfs_buf_item");
1714 if (!xfs_buf_item_zone) 1720 if (!xfs_buf_item_zone)
1715 goto out_destroy_trans_zone; 1721 goto out_destroy_log_item_desc_zone;
1716 1722
1717 xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) + 1723 xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) +
1718 ((XFS_EFD_MAX_FAST_EXTENTS - 1) * 1724 ((XFS_EFD_MAX_FAST_EXTENTS - 1) *
@@ -1749,6 +1755,8 @@ xfs_init_zones(void)
1749 kmem_zone_destroy(xfs_efd_zone); 1755 kmem_zone_destroy(xfs_efd_zone);
1750 out_destroy_buf_item_zone: 1756 out_destroy_buf_item_zone:
1751 kmem_zone_destroy(xfs_buf_item_zone); 1757 kmem_zone_destroy(xfs_buf_item_zone);
1758 out_destroy_log_item_desc_zone:
1759 kmem_zone_destroy(xfs_log_item_desc_zone);
1752 out_destroy_trans_zone: 1760 out_destroy_trans_zone:
1753 kmem_zone_destroy(xfs_trans_zone); 1761 kmem_zone_destroy(xfs_trans_zone);
1754 out_destroy_ifork_zone: 1762 out_destroy_ifork_zone:
@@ -1779,6 +1787,7 @@ xfs_destroy_zones(void)
1779 kmem_zone_destroy(xfs_efi_zone); 1787 kmem_zone_destroy(xfs_efi_zone);
1780 kmem_zone_destroy(xfs_efd_zone); 1788 kmem_zone_destroy(xfs_efd_zone);
1781 kmem_zone_destroy(xfs_buf_item_zone); 1789 kmem_zone_destroy(xfs_buf_item_zone);
1790 kmem_zone_destroy(xfs_log_item_desc_zone);
1782 kmem_zone_destroy(xfs_trans_zone); 1791 kmem_zone_destroy(xfs_trans_zone);
1783 kmem_zone_destroy(xfs_ifork_zone); 1792 kmem_zone_destroy(xfs_ifork_zone);
1784 kmem_zone_destroy(xfs_dabuf_zone); 1793 kmem_zone_destroy(xfs_dabuf_zone);
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 08f5604d092f..7de91d1b75c0 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -49,16 +49,14 @@ xfs_trans_dqjoin(
49 xfs_trans_t *tp, 49 xfs_trans_t *tp,
50 xfs_dquot_t *dqp) 50 xfs_dquot_t *dqp)
51{ 51{
52 xfs_dq_logitem_t *lp = &dqp->q_logitem;
53
54 ASSERT(dqp->q_transp != tp); 52 ASSERT(dqp->q_transp != tp);
55 ASSERT(XFS_DQ_IS_LOCKED(dqp)); 53 ASSERT(XFS_DQ_IS_LOCKED(dqp));
56 ASSERT(lp->qli_dquot == dqp); 54 ASSERT(dqp->q_logitem.qli_dquot == dqp);
57 55
58 /* 56 /*
59 * Get a log_item_desc to point at the new item. 57 * Get a log_item_desc to point at the new item.
60 */ 58 */
61 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(lp)); 59 xfs_trans_add_item(tp, &dqp->q_logitem.qli_item);
62 60
63 /* 61 /*
64 * Initialize i_transp so we can later determine if this dquot is 62 * Initialize i_transp so we can later determine if this dquot is
@@ -83,16 +81,11 @@ xfs_trans_log_dquot(
83 xfs_trans_t *tp, 81 xfs_trans_t *tp,
84 xfs_dquot_t *dqp) 82 xfs_dquot_t *dqp)
85{ 83{
86 xfs_log_item_desc_t *lidp;
87
88 ASSERT(dqp->q_transp == tp); 84 ASSERT(dqp->q_transp == tp);
89 ASSERT(XFS_DQ_IS_LOCKED(dqp)); 85 ASSERT(XFS_DQ_IS_LOCKED(dqp));
90 86
91 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(&dqp->q_logitem));
92 ASSERT(lidp != NULL);
93
94 tp->t_flags |= XFS_TRANS_DIRTY; 87 tp->t_flags |= XFS_TRANS_DIRTY;
95 lidp->lid_flags |= XFS_LID_DIRTY; 88 dqp->q_logitem.qli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
96} 89}
97 90
98/* 91/*
@@ -864,9 +857,8 @@ xfs_trans_get_qoff_item(
864 /* 857 /*
865 * Get a log_item_desc to point at the new item. 858 * Get a log_item_desc to point at the new item.
866 */ 859 */
867 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)q); 860 xfs_trans_add_item(tp, &q->qql_item);
868 861 return q;
869 return (q);
870} 862}
871 863
872 864
@@ -880,13 +872,8 @@ xfs_trans_log_quotaoff_item(
880 xfs_trans_t *tp, 872 xfs_trans_t *tp,
881 xfs_qoff_logitem_t *qlp) 873 xfs_qoff_logitem_t *qlp)
882{ 874{
883 xfs_log_item_desc_t *lidp;
884
885 lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)qlp);
886 ASSERT(lidp != NULL);
887
888 tp->t_flags |= XFS_TRANS_DIRTY; 875 tp->t_flags |= XFS_TRANS_DIRTY;
889 lidp->lid_flags |= XFS_LID_DIRTY; 876 qlp->qql_item.li_desc->lid_flags |= XFS_LID_DIRTY;
890} 877}
891 878
892STATIC void 879STATIC void
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index ed4e3ae2c1d0..ff8675b41973 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5857,43 +5857,18 @@ xfs_bmap_get_bp(
5857 bp = NULL; 5857 bp = NULL;
5858 5858
5859 if (!bp) { /* Chase down all the log items to see if the bp is there */ 5859 if (!bp) { /* Chase down all the log items to see if the bp is there */
5860 xfs_log_item_chunk_t *licp; 5860 struct xfs_log_item_desc *lidp;
5861 xfs_trans_t *tp; 5861 struct xfs_buf_log_item *bip;
5862 5862
5863 tp = cur->bc_tp; 5863 list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) {
5864 licp = &tp->t_items; 5864 bip = (struct xfs_buf_log_item *)lidp->lid_item;
5865 while (!bp && licp != NULL) { 5865 if (bip->bli_item.li_type == XFS_LI_BUF &&
5866 if (xfs_lic_are_all_free(licp)) { 5866 XFS_BUF_ADDR(bip->bli_buf) == bno)
5867 licp = licp->lic_next; 5867 return bip->bli_buf;
5868 continue;
5869 }
5870 for (i = 0; i < licp->lic_unused; i++) {
5871 xfs_log_item_desc_t *lidp;
5872 xfs_log_item_t *lip;
5873 xfs_buf_log_item_t *bip;
5874 xfs_buf_t *lbp;
5875
5876 if (xfs_lic_isfree(licp, i)) {
5877 continue;
5878 }
5879
5880 lidp = xfs_lic_slot(licp, i);
5881 lip = lidp->lid_item;
5882 if (lip->li_type != XFS_LI_BUF)
5883 continue;
5884
5885 bip = (xfs_buf_log_item_t *)lip;
5886 lbp = bip->bli_buf;
5887
5888 if (XFS_BUF_ADDR(lbp) == bno) {
5889 bp = lbp;
5890 break; /* Found it */
5891 }
5892 }
5893 licp = licp->lic_next;
5894 } 5868 }
5895 } 5869 }
5896 return(bp); 5870
5871 return bp;
5897} 5872}
5898 5873
5899STATIC void 5874STATIC void
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 91ad92e83bc6..711f69abbbe4 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -460,13 +460,10 @@ xfs_buf_item_unpin_remove(
460 * occurs later in the xfs_trans_uncommit() will try to 460 * occurs later in the xfs_trans_uncommit() will try to
461 * reference the buffer which we no longer have a hold on. 461 * reference the buffer which we no longer have a hold on.
462 */ 462 */
463 struct xfs_log_item_desc *lidp;
464
465 ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0); 463 ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0);
466 trace_xfs_buf_item_unpin_stale(bip); 464 trace_xfs_buf_item_unpin_stale(bip);
467 465
468 lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)bip); 466 xfs_trans_del_item(&bip->bli_item);
469 xfs_trans_free_item(tp, lidp);
470 467
471 /* 468 /*
472 * Since the transaction no longer refers to the buffer, the 469 * Since the transaction no longer refers to the buffer, the
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 1023b1fadfe8..8d0e543ca3c0 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -131,18 +131,18 @@ STATIC void
131xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) 131xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
132{ 132{
133 struct xfs_ail *ailp = efip->efi_item.li_ailp; 133 struct xfs_ail *ailp = efip->efi_item.li_ailp;
134 xfs_log_item_desc_t *lidp;
135 134
136 spin_lock(&ailp->xa_lock); 135 spin_lock(&ailp->xa_lock);
137 if (efip->efi_flags & XFS_EFI_CANCELED) { 136 if (efip->efi_flags & XFS_EFI_CANCELED) {
137 struct xfs_log_item *lip = &efip->efi_item;
138
138 /* 139 /*
139 * free the xaction descriptor pointing to this item 140 * free the xaction descriptor pointing to this item
140 */ 141 */
141 lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip); 142 xfs_trans_del_item(lip);
142 xfs_trans_free_item(tp, lidp);
143 143
144 /* xfs_trans_ail_delete() drops the AIL lock. */ 144 /* xfs_trans_ail_delete() drops the AIL lock. */
145 xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); 145 xfs_trans_ail_delete(ailp, lip);
146 xfs_efi_item_free(efip); 146 xfs_efi_item_free(efip);
147 } else { 147 } else {
148 efip->efi_flags |= XFS_EFI_COMMITTED; 148 efip->efi_flags |= XFS_EFI_COMMITTED;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 57c53f7ad2c9..9c41efccf728 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * Copyright (C) 2010 Red Hat, Inc.
3 * All Rights Reserved. 4 * All Rights Reserved.
4 * 5 *
5 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -43,6 +44,7 @@
43#include "xfs_trace.h" 44#include "xfs_trace.h"
44 45
45kmem_zone_t *xfs_trans_zone; 46kmem_zone_t *xfs_trans_zone;
47kmem_zone_t *xfs_log_item_desc_zone;
46 48
47 49
48/* 50/*
@@ -593,8 +595,7 @@ _xfs_trans_alloc(
593 tp->t_magic = XFS_TRANS_MAGIC; 595 tp->t_magic = XFS_TRANS_MAGIC;
594 tp->t_type = type; 596 tp->t_type = type;
595 tp->t_mountp = mp; 597 tp->t_mountp = mp;
596 tp->t_items_free = XFS_LIC_NUM_SLOTS; 598 INIT_LIST_HEAD(&tp->t_items);
597 xfs_lic_init(&(tp->t_items));
598 INIT_LIST_HEAD(&tp->t_busy); 599 INIT_LIST_HEAD(&tp->t_busy);
599 return tp; 600 return tp;
600} 601}
@@ -639,8 +640,7 @@ xfs_trans_dup(
639 ntp->t_magic = XFS_TRANS_MAGIC; 640 ntp->t_magic = XFS_TRANS_MAGIC;
640 ntp->t_type = tp->t_type; 641 ntp->t_type = tp->t_type;
641 ntp->t_mountp = tp->t_mountp; 642 ntp->t_mountp = tp->t_mountp;
642 ntp->t_items_free = XFS_LIC_NUM_SLOTS; 643 INIT_LIST_HEAD(&ntp->t_items);
643 xfs_lic_init(&(ntp->t_items));
644 INIT_LIST_HEAD(&ntp->t_busy); 644 INIT_LIST_HEAD(&ntp->t_busy);
645 645
646 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 646 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
@@ -1120,6 +1120,108 @@ xfs_trans_unreserve_and_mod_sb(
1120} 1120}
1121 1121
1122/* 1122/*
1123 * Add the given log item to the transaction's list of log items.
1124 *
1125 * The log item will now point to its new descriptor with its li_desc field.
1126 */
1127void
1128xfs_trans_add_item(
1129 struct xfs_trans *tp,
1130 struct xfs_log_item *lip)
1131{
1132 struct xfs_log_item_desc *lidp;
1133
1134 ASSERT(lip->li_mountp = tp->t_mountp);
1135 ASSERT(lip->li_ailp = tp->t_mountp->m_ail);
1136
1137 lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP);
1138
1139 lidp->lid_item = lip;
1140 lidp->lid_flags = 0;
1141 lidp->lid_size = 0;
1142 list_add_tail(&lidp->lid_trans, &tp->t_items);
1143
1144 lip->li_desc = lidp;
1145}
1146
1147STATIC void
1148xfs_trans_free_item_desc(
1149 struct xfs_log_item_desc *lidp)
1150{
1151 list_del_init(&lidp->lid_trans);
1152 kmem_zone_free(xfs_log_item_desc_zone, lidp);
1153}
1154
1155/*
1156 * Unlink and free the given descriptor.
1157 */
1158void
1159xfs_trans_del_item(
1160 struct xfs_log_item *lip)
1161{
1162 xfs_trans_free_item_desc(lip->li_desc);
1163 lip->li_desc = NULL;
1164}
1165
1166/*
1167 * Unlock all of the items of a transaction and free all the descriptors
1168 * of that transaction.
1169 */
1170STATIC void
1171xfs_trans_free_items(
1172 struct xfs_trans *tp,
1173 xfs_lsn_t commit_lsn,
1174 int flags)
1175{
1176 struct xfs_log_item_desc *lidp, *next;
1177
1178 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1179 struct xfs_log_item *lip = lidp->lid_item;
1180
1181 lip->li_desc = NULL;
1182
1183 if (commit_lsn != NULLCOMMITLSN)
1184 IOP_COMMITTING(lip, commit_lsn);
1185 if (flags & XFS_TRANS_ABORT)
1186 lip->li_flags |= XFS_LI_ABORTED;
1187 IOP_UNLOCK(lip);
1188
1189 xfs_trans_free_item_desc(lidp);
1190 }
1191}
1192
1193/*
1194 * Unlock the items associated with a transaction.
1195 *
1196 * Items which were not logged should be freed. Those which were logged must
1197 * still be tracked so they can be unpinned when the transaction commits.
1198 */
1199STATIC void
1200xfs_trans_unlock_items(
1201 struct xfs_trans *tp,
1202 xfs_lsn_t commit_lsn)
1203{
1204 struct xfs_log_item_desc *lidp, *next;
1205
1206 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1207 struct xfs_log_item *lip = lidp->lid_item;
1208
1209 lip->li_desc = NULL;
1210
1211 if (commit_lsn != NULLCOMMITLSN)
1212 IOP_COMMITTING(lip, commit_lsn);
1213 IOP_UNLOCK(lip);
1214
1215 /*
1216 * Free the descriptor if the item is not dirty
1217 * within this transaction.
1218 */
1219 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1220 xfs_trans_free_item_desc(lidp);
1221 }
1222}
1223
1224/*
1123 * Total up the number of log iovecs needed to commit this 1225 * Total up the number of log iovecs needed to commit this
1124 * transaction. The transaction itself needs one for the 1226 * transaction. The transaction itself needs one for the
1125 * transaction header. Ask each dirty item in turn how many 1227 * transaction header. Ask each dirty item in turn how many
@@ -1130,30 +1232,27 @@ xfs_trans_count_vecs(
1130 struct xfs_trans *tp) 1232 struct xfs_trans *tp)
1131{ 1233{
1132 int nvecs; 1234 int nvecs;
1133 xfs_log_item_desc_t *lidp; 1235 struct xfs_log_item_desc *lidp;
1134 1236
1135 nvecs = 1; 1237 nvecs = 1;
1136 lidp = xfs_trans_first_item(tp);
1137 ASSERT(lidp != NULL);
1138 1238
1139 /* In the non-debug case we need to start bailing out if we 1239 /* In the non-debug case we need to start bailing out if we
1140 * didn't find a log_item here, return zero and let trans_commit 1240 * didn't find a log_item here, return zero and let trans_commit
1141 * deal with it. 1241 * deal with it.
1142 */ 1242 */
1143 if (lidp == NULL) 1243 if (list_empty(&tp->t_items)) {
1244 ASSERT(0);
1144 return 0; 1245 return 0;
1246 }
1145 1247
1146 while (lidp != NULL) { 1248 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1147 /* 1249 /*
1148 * Skip items which aren't dirty in this transaction. 1250 * Skip items which aren't dirty in this transaction.
1149 */ 1251 */
1150 if (!(lidp->lid_flags & XFS_LID_DIRTY)) { 1252 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1151 lidp = xfs_trans_next_item(tp, lidp);
1152 continue; 1253 continue;
1153 }
1154 lidp->lid_size = IOP_SIZE(lidp->lid_item); 1254 lidp->lid_size = IOP_SIZE(lidp->lid_item);
1155 nvecs += lidp->lid_size; 1255 nvecs += lidp->lid_size;
1156 lidp = xfs_trans_next_item(tp, lidp);
1157 } 1256 }
1158 1257
1159 return nvecs; 1258 return nvecs;
@@ -1173,7 +1272,7 @@ xfs_trans_fill_vecs(
1173 struct xfs_trans *tp, 1272 struct xfs_trans *tp,
1174 struct xfs_log_iovec *log_vector) 1273 struct xfs_log_iovec *log_vector)
1175{ 1274{
1176 xfs_log_item_desc_t *lidp; 1275 struct xfs_log_item_desc *lidp;
1177 struct xfs_log_iovec *vecp; 1276 struct xfs_log_iovec *vecp;
1178 uint nitems; 1277 uint nitems;
1179 1278
@@ -1184,14 +1283,11 @@ xfs_trans_fill_vecs(
1184 vecp = log_vector + 1; 1283 vecp = log_vector + 1;
1185 1284
1186 nitems = 0; 1285 nitems = 0;
1187 lidp = xfs_trans_first_item(tp); 1286 ASSERT(!list_empty(&tp->t_items));
1188 ASSERT(lidp); 1287 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1189 while (lidp) {
1190 /* Skip items which aren't dirty in this transaction. */ 1288 /* Skip items which aren't dirty in this transaction. */
1191 if (!(lidp->lid_flags & XFS_LID_DIRTY)) { 1289 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1192 lidp = xfs_trans_next_item(tp, lidp);
1193 continue; 1290 continue;
1194 }
1195 1291
1196 /* 1292 /*
1197 * The item may be marked dirty but not log anything. This can 1293 * The item may be marked dirty but not log anything. This can
@@ -1202,7 +1298,6 @@ xfs_trans_fill_vecs(
1202 IOP_FORMAT(lidp->lid_item, vecp); 1298 IOP_FORMAT(lidp->lid_item, vecp);
1203 vecp += lidp->lid_size; 1299 vecp += lidp->lid_size;
1204 IOP_PIN(lidp->lid_item); 1300 IOP_PIN(lidp->lid_item);
1205 lidp = xfs_trans_next_item(tp, lidp);
1206 } 1301 }
1207 1302
1208 /* 1303 /*
@@ -1297,24 +1392,15 @@ xfs_trans_committed(
1297 struct xfs_trans *tp, 1392 struct xfs_trans *tp,
1298 int abortflag) 1393 int abortflag)
1299{ 1394{
1300 xfs_log_item_desc_t *lidp; 1395 struct xfs_log_item_desc *lidp, *next;
1301 xfs_log_item_chunk_t *licp;
1302 xfs_log_item_chunk_t *next_licp;
1303 1396
1304 /* Call the transaction's completion callback if there is one. */ 1397 /* Call the transaction's completion callback if there is one. */
1305 if (tp->t_callback != NULL) 1398 if (tp->t_callback != NULL)
1306 tp->t_callback(tp, tp->t_callarg); 1399 tp->t_callback(tp, tp->t_callarg);
1307 1400
1308 for (lidp = xfs_trans_first_item(tp); 1401 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1309 lidp != NULL;
1310 lidp = xfs_trans_next_item(tp, lidp)) {
1311 xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag); 1402 xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
1312 } 1403 xfs_trans_free_item_desc(lidp);
1313
1314 /* free the item chunks, ignoring the embedded chunk */
1315 for (licp = tp->t_items.lic_next; licp != NULL; licp = next_licp) {
1316 next_licp = licp->lic_next;
1317 kmem_free(licp);
1318 } 1404 }
1319 1405
1320 xfs_trans_free(tp); 1406 xfs_trans_free(tp);
@@ -1329,11 +1415,9 @@ xfs_trans_uncommit(
1329 struct xfs_trans *tp, 1415 struct xfs_trans *tp,
1330 uint flags) 1416 uint flags)
1331{ 1417{
1332 xfs_log_item_desc_t *lidp; 1418 struct xfs_log_item_desc *lidp;
1333 1419
1334 for (lidp = xfs_trans_first_item(tp); 1420 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1335 lidp != NULL;
1336 lidp = xfs_trans_next_item(tp, lidp)) {
1337 /* 1421 /*
1338 * Unpin all but those that aren't dirty. 1422 * Unpin all but those that aren't dirty.
1339 */ 1423 */
@@ -1504,33 +1588,28 @@ STATIC struct xfs_log_vec *
1504xfs_trans_alloc_log_vecs( 1588xfs_trans_alloc_log_vecs(
1505 xfs_trans_t *tp) 1589 xfs_trans_t *tp)
1506{ 1590{
1507 xfs_log_item_desc_t *lidp; 1591 struct xfs_log_item_desc *lidp;
1508 struct xfs_log_vec *lv = NULL; 1592 struct xfs_log_vec *lv = NULL;
1509 struct xfs_log_vec *ret_lv = NULL; 1593 struct xfs_log_vec *ret_lv = NULL;
1510 1594
1511 lidp = xfs_trans_first_item(tp);
1512 1595
1513 /* Bail out if we didn't find a log item. */ 1596 /* Bail out if we didn't find a log item. */
1514 if (!lidp) { 1597 if (list_empty(&tp->t_items)) {
1515 ASSERT(0); 1598 ASSERT(0);
1516 return NULL; 1599 return NULL;
1517 } 1600 }
1518 1601
1519 while (lidp != NULL) { 1602 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
1520 struct xfs_log_vec *new_lv; 1603 struct xfs_log_vec *new_lv;
1521 1604
1522 /* Skip items which aren't dirty in this transaction. */ 1605 /* Skip items which aren't dirty in this transaction. */
1523 if (!(lidp->lid_flags & XFS_LID_DIRTY)) { 1606 if (!(lidp->lid_flags & XFS_LID_DIRTY))
1524 lidp = xfs_trans_next_item(tp, lidp);
1525 continue; 1607 continue;
1526 }
1527 1608
1528 /* Skip items that do not have any vectors for writing */ 1609 /* Skip items that do not have any vectors for writing */
1529 lidp->lid_size = IOP_SIZE(lidp->lid_item); 1610 lidp->lid_size = IOP_SIZE(lidp->lid_item);
1530 if (!lidp->lid_size) { 1611 if (!lidp->lid_size)
1531 lidp = xfs_trans_next_item(tp, lidp);
1532 continue; 1612 continue;
1533 }
1534 1613
1535 new_lv = kmem_zalloc(sizeof(*new_lv) + 1614 new_lv = kmem_zalloc(sizeof(*new_lv) +
1536 lidp->lid_size * sizeof(struct xfs_log_iovec), 1615 lidp->lid_size * sizeof(struct xfs_log_iovec),
@@ -1545,7 +1624,6 @@ xfs_trans_alloc_log_vecs(
1545 else 1624 else
1546 lv->lv_next = new_lv; 1625 lv->lv_next = new_lv;
1547 lv = new_lv; 1626 lv = new_lv;
1548 lidp = xfs_trans_next_item(tp, lidp);
1549 } 1627 }
1550 1628
1551 return ret_lv; 1629 return ret_lv;
@@ -1704,12 +1782,6 @@ xfs_trans_cancel(
1704 int flags) 1782 int flags)
1705{ 1783{
1706 int log_flags; 1784 int log_flags;
1707#ifdef DEBUG
1708 xfs_log_item_chunk_t *licp;
1709 xfs_log_item_desc_t *lidp;
1710 xfs_log_item_t *lip;
1711 int i;
1712#endif
1713 xfs_mount_t *mp = tp->t_mountp; 1785 xfs_mount_t *mp = tp->t_mountp;
1714 1786
1715 /* 1787 /*
@@ -1728,21 +1800,11 @@ xfs_trans_cancel(
1728 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 1800 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1729 } 1801 }
1730#ifdef DEBUG 1802#ifdef DEBUG
1731 if (!(flags & XFS_TRANS_ABORT)) { 1803 if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) {
1732 licp = &(tp->t_items); 1804 struct xfs_log_item_desc *lidp;
1733 while (licp != NULL) { 1805
1734 lidp = licp->lic_descs; 1806 list_for_each_entry(lidp, &tp->t_items, lid_trans)
1735 for (i = 0; i < licp->lic_unused; i++, lidp++) { 1807 ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD));
1736 if (xfs_lic_isfree(licp, i)) {
1737 continue;
1738 }
1739
1740 lip = lidp->lid_item;
1741 if (!XFS_FORCED_SHUTDOWN(mp))
1742 ASSERT(!(lip->li_type == XFS_LI_EFD));
1743 }
1744 licp = licp->lic_next;
1745 }
1746 } 1808 }
1747#endif 1809#endif
1748 xfs_trans_unreserve_and_mod_sb(tp); 1810 xfs_trans_unreserve_and_mod_sb(tp);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index e639e8e9a2a9..0c903eb8bbe1 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -161,105 +161,14 @@ typedef struct xfs_trans_header {
161 * the amount of space needed to log the item it describes 161 * the amount of space needed to log the item it describes
162 * once we get to commit processing (see xfs_trans_commit()). 162 * once we get to commit processing (see xfs_trans_commit()).
163 */ 163 */
164typedef struct xfs_log_item_desc { 164struct xfs_log_item_desc {
165 struct xfs_log_item *lid_item; 165 struct xfs_log_item *lid_item;
166 ushort lid_size; 166 ushort lid_size;
167 unsigned char lid_flags; 167 unsigned char lid_flags;
168 unsigned char lid_index; 168 struct list_head lid_trans;
169} xfs_log_item_desc_t; 169};
170 170
171#define XFS_LID_DIRTY 0x1 171#define XFS_LID_DIRTY 0x1
172#define XFS_LID_PINNED 0x2
173
174/*
175 * This structure is used to maintain a chunk list of log_item_desc
176 * structures. The free field is a bitmask indicating which descriptors
177 * in this chunk's array are free. The unused field is the first value
178 * not used since this chunk was allocated.
179 */
180#define XFS_LIC_NUM_SLOTS 15
181typedef struct xfs_log_item_chunk {
182 struct xfs_log_item_chunk *lic_next;
183 ushort lic_free;
184 ushort lic_unused;
185 xfs_log_item_desc_t lic_descs[XFS_LIC_NUM_SLOTS];
186} xfs_log_item_chunk_t;
187
188#define XFS_LIC_MAX_SLOT (XFS_LIC_NUM_SLOTS - 1)
189#define XFS_LIC_FREEMASK ((1 << XFS_LIC_NUM_SLOTS) - 1)
190
191
192/*
193 * Initialize the given chunk. Set the chunk's free descriptor mask
194 * to indicate that all descriptors are free. The caller gets to set
195 * lic_unused to the right value (0 matches all free). The
196 * lic_descs.lid_index values are set up as each desc is allocated.
197 */
198static inline void xfs_lic_init(xfs_log_item_chunk_t *cp)
199{
200 cp->lic_free = XFS_LIC_FREEMASK;
201}
202
203static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot)
204{
205 cp->lic_descs[slot].lid_index = (unsigned char)(slot);
206}
207
208static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp)
209{
210 return cp->lic_free & XFS_LIC_FREEMASK;
211}
212
213static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp)
214{
215 cp->lic_free = XFS_LIC_FREEMASK;
216}
217
218static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp)
219{
220 return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK);
221}
222
223static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot)
224{
225 return (cp->lic_free & (1 << slot));
226}
227
228static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot)
229{
230 cp->lic_free &= ~(1 << slot);
231}
232
233static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot)
234{
235 cp->lic_free |= 1 << slot;
236}
237
238static inline xfs_log_item_desc_t *
239xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot)
240{
241 return &(cp->lic_descs[slot]);
242}
243
244static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp)
245{
246 return (uint)dp->lid_index;
247}
248
249/*
250 * Calculate the address of a chunk given a descriptor pointer:
251 * dp - dp->lid_index give the address of the start of the lic_descs array.
252 * From this we subtract the offset of the lic_descs field in a chunk.
253 * All of this yields the address of the chunk, which is
254 * cast to a chunk pointer.
255 */
256static inline xfs_log_item_chunk_t *
257xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
258{
259 return (xfs_log_item_chunk_t*) \
260 (((xfs_caddr_t)((dp) - (dp)->lid_index)) - \
261 (xfs_caddr_t)(((xfs_log_item_chunk_t*)0)->lic_descs));
262}
263 172
264#define XFS_TRANS_MAGIC 0x5452414E /* 'TRAN' */ 173#define XFS_TRANS_MAGIC 0x5452414E /* 'TRAN' */
265/* 174/*
@@ -516,8 +425,7 @@ typedef struct xfs_trans {
516 int64_t t_rblocks_delta;/* superblock rblocks change */ 425 int64_t t_rblocks_delta;/* superblock rblocks change */
517 int64_t t_rextents_delta;/* superblocks rextents chg */ 426 int64_t t_rextents_delta;/* superblocks rextents chg */
518 int64_t t_rextslog_delta;/* superblocks rextslog chg */ 427 int64_t t_rextslog_delta;/* superblocks rextslog chg */
519 unsigned int t_items_free; /* log item descs free */ 428 struct list_head t_items; /* log item descriptors */
520 xfs_log_item_chunk_t t_items; /* first log item desc chunk */
521 xfs_trans_header_t t_header; /* header for in-log trans */ 429 xfs_trans_header_t t_header; /* header for in-log trans */
522 struct list_head t_busy; /* list of busy extents */ 430 struct list_head t_busy; /* list of busy extents */
523 unsigned long t_pflags; /* saved process flags state */ 431 unsigned long t_pflags; /* saved process flags state */
@@ -595,6 +503,7 @@ int xfs_trans_ail_init(struct xfs_mount *);
595void xfs_trans_ail_destroy(struct xfs_mount *); 503void xfs_trans_ail_destroy(struct xfs_mount *);
596 504
597extern kmem_zone_t *xfs_trans_zone; 505extern kmem_zone_t *xfs_trans_zone;
506extern kmem_zone_t *xfs_log_item_desc_zone;
598 507
599#endif /* __KERNEL__ */ 508#endif /* __KERNEL__ */
600 509
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index d1d08aa404b5..74a1c33e4098 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -47,36 +47,17 @@ xfs_trans_buf_item_match(
47 xfs_daddr_t blkno, 47 xfs_daddr_t blkno,
48 int len) 48 int len)
49{ 49{
50 xfs_log_item_chunk_t *licp; 50 struct xfs_log_item_desc *lidp;
51 xfs_log_item_desc_t *lidp; 51 struct xfs_buf_log_item *blip;
52 xfs_buf_log_item_t *blip;
53 int i;
54 52
55 len = BBTOB(len); 53 len = BBTOB(len);
56 for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { 54 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
57 if (xfs_lic_are_all_free(licp)) { 55 blip = (struct xfs_buf_log_item *)lidp->lid_item;
58 ASSERT(licp == &tp->t_items); 56 if (blip->bli_item.li_type == XFS_LI_BUF &&
59 ASSERT(licp->lic_next == NULL); 57 XFS_BUF_TARGET(blip->bli_buf) == target &&
60 return NULL; 58 XFS_BUF_ADDR(blip->bli_buf) == blkno &&
61 } 59 XFS_BUF_COUNT(blip->bli_buf) == len)
62 60 return blip->bli_buf;
63 for (i = 0; i < licp->lic_unused; i++) {
64 /*
65 * Skip unoccupied slots.
66 */
67 if (xfs_lic_isfree(licp, i))
68 continue;
69
70 lidp = xfs_lic_slot(licp, i);
71 blip = (xfs_buf_log_item_t *)lidp->lid_item;
72 if (blip->bli_item.li_type != XFS_LI_BUF)
73 continue;
74
75 if (XFS_BUF_TARGET(blip->bli_buf) == target &&
76 XFS_BUF_ADDR(blip->bli_buf) == blkno &&
77 XFS_BUF_COUNT(blip->bli_buf) == len)
78 return blip->bli_buf;
79 }
80 } 61 }
81 62
82 return NULL; 63 return NULL;
@@ -123,7 +104,7 @@ _xfs_trans_bjoin(
123 /* 104 /*
124 * Get a log_item_desc to point at the new item. 105 * Get a log_item_desc to point at the new item.
125 */ 106 */
126 (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip); 107 xfs_trans_add_item(tp, &bip->bli_item);
127 108
128 /* 109 /*
129 * Initialize b_fsprivate2 so we can find it with incore_match() 110 * Initialize b_fsprivate2 so we can find it with incore_match()
@@ -479,7 +460,6 @@ xfs_trans_brelse(xfs_trans_t *tp,
479{ 460{
480 xfs_buf_log_item_t *bip; 461 xfs_buf_log_item_t *bip;
481 xfs_log_item_t *lip; 462 xfs_log_item_t *lip;
482 xfs_log_item_desc_t *lidp;
483 463
484 /* 464 /*
485 * Default to a normal brelse() call if the tp is NULL. 465 * Default to a normal brelse() call if the tp is NULL.
@@ -510,13 +490,6 @@ xfs_trans_brelse(xfs_trans_t *tp,
510 ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); 490 ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
511 ASSERT(atomic_read(&bip->bli_refcount) > 0); 491 ASSERT(atomic_read(&bip->bli_refcount) > 0);
512 492
513 /*
514 * Find the item descriptor pointing to this buffer's
515 * log item. It must be there.
516 */
517 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
518 ASSERT(lidp != NULL);
519
520 trace_xfs_trans_brelse(bip); 493 trace_xfs_trans_brelse(bip);
521 494
522 /* 495 /*
@@ -532,7 +505,7 @@ xfs_trans_brelse(xfs_trans_t *tp,
532 * If the buffer is dirty within this transaction, we can't 505 * If the buffer is dirty within this transaction, we can't
533 * release it until we commit. 506 * release it until we commit.
534 */ 507 */
535 if (lidp->lid_flags & XFS_LID_DIRTY) 508 if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY)
536 return; 509 return;
537 510
538 /* 511 /*
@@ -549,7 +522,7 @@ xfs_trans_brelse(xfs_trans_t *tp,
549 /* 522 /*
550 * Free up the log item descriptor tracking the released item. 523 * Free up the log item descriptor tracking the released item.
551 */ 524 */
552 xfs_trans_free_item(tp, lidp); 525 xfs_trans_del_item(&bip->bli_item);
553 526
554 /* 527 /*
555 * Clear the hold flag in the buf log item if it is set. 528 * Clear the hold flag in the buf log item if it is set.
@@ -661,7 +634,6 @@ xfs_trans_log_buf(xfs_trans_t *tp,
661 uint last) 634 uint last)
662{ 635{
663 xfs_buf_log_item_t *bip; 636 xfs_buf_log_item_t *bip;
664 xfs_log_item_desc_t *lidp;
665 637
666 ASSERT(XFS_BUF_ISBUSY(bp)); 638 ASSERT(XFS_BUF_ISBUSY(bp));
667 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 639 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
@@ -703,11 +675,8 @@ xfs_trans_log_buf(xfs_trans_t *tp,
703 bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL; 675 bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL;
704 } 676 }
705 677
706 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
707 ASSERT(lidp != NULL);
708
709 tp->t_flags |= XFS_TRANS_DIRTY; 678 tp->t_flags |= XFS_TRANS_DIRTY;
710 lidp->lid_flags |= XFS_LID_DIRTY; 679 bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
711 bip->bli_flags |= XFS_BLI_LOGGED; 680 bip->bli_flags |= XFS_BLI_LOGGED;
712 xfs_buf_item_log(bip, first, last); 681 xfs_buf_item_log(bip, first, last);
713} 682}
@@ -736,7 +705,6 @@ xfs_trans_binval(
736 xfs_trans_t *tp, 705 xfs_trans_t *tp,
737 xfs_buf_t *bp) 706 xfs_buf_t *bp)
738{ 707{
739 xfs_log_item_desc_t *lidp;
740 xfs_buf_log_item_t *bip; 708 xfs_buf_log_item_t *bip;
741 709
742 ASSERT(XFS_BUF_ISBUSY(bp)); 710 ASSERT(XFS_BUF_ISBUSY(bp));
@@ -744,8 +712,6 @@ xfs_trans_binval(
744 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 712 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
745 713
746 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 714 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
747 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
748 ASSERT(lidp != NULL);
749 ASSERT(atomic_read(&bip->bli_refcount) > 0); 715 ASSERT(atomic_read(&bip->bli_refcount) > 0);
750 716
751 trace_xfs_trans_binval(bip); 717 trace_xfs_trans_binval(bip);
@@ -760,7 +726,7 @@ xfs_trans_binval(
760 ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); 726 ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
761 ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF)); 727 ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF));
762 ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); 728 ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
763 ASSERT(lidp->lid_flags & XFS_LID_DIRTY); 729 ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY);
764 ASSERT(tp->t_flags & XFS_TRANS_DIRTY); 730 ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
765 return; 731 return;
766 } 732 }
@@ -793,7 +759,7 @@ xfs_trans_binval(
793 bip->bli_format.blf_flags |= XFS_BLF_CANCEL; 759 bip->bli_format.blf_flags |= XFS_BLF_CANCEL;
794 memset((char *)(bip->bli_format.blf_data_map), 0, 760 memset((char *)(bip->bli_format.blf_data_map), 0,
795 (bip->bli_format.blf_map_size * sizeof(uint))); 761 (bip->bli_format.blf_map_size * sizeof(uint)));
796 lidp->lid_flags |= XFS_LID_DIRTY; 762 bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
797 tp->t_flags |= XFS_TRANS_DIRTY; 763 tp->t_flags |= XFS_TRANS_DIRTY;
798} 764}
799 765
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index dfb6a0fdcf9c..f783d5e9fa70 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -48,9 +48,8 @@ xfs_trans_get_efi(xfs_trans_t *tp,
48 /* 48 /*
49 * Get a log_item_desc to point at the new item. 49 * Get a log_item_desc to point at the new item.
50 */ 50 */
51 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)efip); 51 xfs_trans_add_item(tp, &efip->efi_item);
52 52 return efip;
53 return (efip);
54} 53}
55 54
56/* 55/*
@@ -64,15 +63,11 @@ xfs_trans_log_efi_extent(xfs_trans_t *tp,
64 xfs_fsblock_t start_block, 63 xfs_fsblock_t start_block,
65 xfs_extlen_t ext_len) 64 xfs_extlen_t ext_len)
66{ 65{
67 xfs_log_item_desc_t *lidp;
68 uint next_extent; 66 uint next_extent;
69 xfs_extent_t *extp; 67 xfs_extent_t *extp;
70 68
71 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efip);
72 ASSERT(lidp != NULL);
73
74 tp->t_flags |= XFS_TRANS_DIRTY; 69 tp->t_flags |= XFS_TRANS_DIRTY;
75 lidp->lid_flags |= XFS_LID_DIRTY; 70 efip->efi_item.li_desc->lid_flags |= XFS_LID_DIRTY;
76 71
77 next_extent = efip->efi_next_extent; 72 next_extent = efip->efi_next_extent;
78 ASSERT(next_extent < efip->efi_format.efi_nextents); 73 ASSERT(next_extent < efip->efi_format.efi_nextents);
@@ -105,9 +100,8 @@ xfs_trans_get_efd(xfs_trans_t *tp,
105 /* 100 /*
106 * Get a log_item_desc to point at the new item. 101 * Get a log_item_desc to point at the new item.
107 */ 102 */
108 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)efdp); 103 xfs_trans_add_item(tp, &efdp->efd_item);
109 104 return efdp;
110 return (efdp);
111} 105}
112 106
113/* 107/*
@@ -121,15 +115,11 @@ xfs_trans_log_efd_extent(xfs_trans_t *tp,
121 xfs_fsblock_t start_block, 115 xfs_fsblock_t start_block,
122 xfs_extlen_t ext_len) 116 xfs_extlen_t ext_len)
123{ 117{
124 xfs_log_item_desc_t *lidp;
125 uint next_extent; 118 uint next_extent;
126 xfs_extent_t *extp; 119 xfs_extent_t *extp;
127 120
128 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efdp);
129 ASSERT(lidp != NULL);
130
131 tp->t_flags |= XFS_TRANS_DIRTY; 121 tp->t_flags |= XFS_TRANS_DIRTY;
132 lidp->lid_flags |= XFS_LID_DIRTY; 122 efdp->efd_item.li_desc->lid_flags |= XFS_LID_DIRTY;
133 123
134 next_extent = efdp->efd_next_extent; 124 next_extent = efdp->efd_next_extent;
135 ASSERT(next_extent < efdp->efd_format.efd_nextents); 125 ASSERT(next_extent < efdp->efd_format.efd_nextents);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 04cc08a1b663..865eeb63ce16 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -88,7 +88,7 @@ xfs_trans_ijoin(
88 /* 88 /*
89 * Get a log_item_desc to point at the new item. 89 * Get a log_item_desc to point at the new item.
90 */ 90 */
91 (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(iip)); 91 xfs_trans_add_item(tp, &iip->ili_item);
92 92
93 xfs_trans_inode_broot_debug(ip); 93 xfs_trans_inode_broot_debug(ip);
94 94
@@ -144,17 +144,12 @@ xfs_trans_log_inode(
144 xfs_inode_t *ip, 144 xfs_inode_t *ip,
145 uint flags) 145 uint flags)
146{ 146{
147 xfs_log_item_desc_t *lidp;
148
149 ASSERT(ip->i_transp == tp); 147 ASSERT(ip->i_transp == tp);
150 ASSERT(ip->i_itemp != NULL); 148 ASSERT(ip->i_itemp != NULL);
151 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 149 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
152 150
153 lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp));
154 ASSERT(lidp != NULL);
155
156 tp->t_flags |= XFS_TRANS_DIRTY; 151 tp->t_flags |= XFS_TRANS_DIRTY;
157 lidp->lid_flags |= XFS_LID_DIRTY; 152 ip->i_itemp->ili_item.li_desc->lid_flags |= XFS_LID_DIRTY;
158 153
159 /* 154 /*
160 * Always OR in the bits from the ili_last_fields field. 155 * Always OR in the bits from the ili_last_fields field.
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
deleted file mode 100644
index 55035a7401cb..000000000000
--- a/fs/xfs/xfs_trans_item.c
+++ /dev/null
@@ -1,440 +0,0 @@
1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_log.h"
22#include "xfs_inum.h"
23#include "xfs_trans.h"
24#include "xfs_trans_priv.h"
25/* XXX: from here down needed until struct xfs_trans has its own ailp */
26#include "xfs_bit.h"
27#include "xfs_buf_item.h"
28#include "xfs_sb.h"
29#include "xfs_ag.h"
30#include "xfs_dir2.h"
31#include "xfs_mount.h"
32
33STATIC int xfs_trans_unlock_chunk(xfs_log_item_chunk_t *,
34 int, int, xfs_lsn_t);
35
36/*
37 * This is called to add the given log item to the transaction's
38 * list of log items. It must find a free log item descriptor
39 * or allocate a new one and add the item to that descriptor.
40 * The function returns a pointer to item descriptor used to point
41 * to the new item. The log item will now point to its new descriptor
42 * with its li_desc field.
43 */
44xfs_log_item_desc_t *
45xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
46{
47 xfs_log_item_desc_t *lidp;
48 xfs_log_item_chunk_t *licp;
49 int i=0;
50
51 /*
52 * If there are no free descriptors, allocate a new chunk
53 * of them and put it at the front of the chunk list.
54 */
55 if (tp->t_items_free == 0) {
56 licp = (xfs_log_item_chunk_t*)
57 kmem_alloc(sizeof(xfs_log_item_chunk_t), KM_SLEEP);
58 ASSERT(licp != NULL);
59 /*
60 * Initialize the chunk, and then
61 * claim the first slot in the newly allocated chunk.
62 */
63 xfs_lic_init(licp);
64 xfs_lic_claim(licp, 0);
65 licp->lic_unused = 1;
66 xfs_lic_init_slot(licp, 0);
67 lidp = xfs_lic_slot(licp, 0);
68
69 /*
70 * Link in the new chunk and update the free count.
71 */
72 licp->lic_next = tp->t_items.lic_next;
73 tp->t_items.lic_next = licp;
74 tp->t_items_free = XFS_LIC_NUM_SLOTS - 1;
75
76 /*
77 * Initialize the descriptor and the generic portion
78 * of the log item.
79 *
80 * Point the new slot at this item and return it.
81 * Also point the log item at its currently active
82 * descriptor and set the item's mount pointer.
83 */
84 lidp->lid_item = lip;
85 lidp->lid_flags = 0;
86 lidp->lid_size = 0;
87 lip->li_desc = lidp;
88 lip->li_mountp = tp->t_mountp;
89 lip->li_ailp = tp->t_mountp->m_ail;
90 return lidp;
91 }
92
93 /*
94 * Find the free descriptor. It is somewhere in the chunklist
95 * of descriptors.
96 */
97 licp = &tp->t_items;
98 while (licp != NULL) {
99 if (xfs_lic_vacancy(licp)) {
100 if (licp->lic_unused <= XFS_LIC_MAX_SLOT) {
101 i = licp->lic_unused;
102 ASSERT(xfs_lic_isfree(licp, i));
103 break;
104 }
105 for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) {
106 if (xfs_lic_isfree(licp, i))
107 break;
108 }
109 ASSERT(i <= XFS_LIC_MAX_SLOT);
110 break;
111 }
112 licp = licp->lic_next;
113 }
114 ASSERT(licp != NULL);
115 /*
116 * If we find a free descriptor, claim it,
117 * initialize it, and return it.
118 */
119 xfs_lic_claim(licp, i);
120 if (licp->lic_unused <= i) {
121 licp->lic_unused = i + 1;
122 xfs_lic_init_slot(licp, i);
123 }
124 lidp = xfs_lic_slot(licp, i);
125 tp->t_items_free--;
126 lidp->lid_item = lip;
127 lidp->lid_flags = 0;
128 lidp->lid_size = 0;
129 lip->li_desc = lidp;
130 lip->li_mountp = tp->t_mountp;
131 lip->li_ailp = tp->t_mountp->m_ail;
132 return lidp;
133}
134
135/*
136 * Free the given descriptor.
137 *
138 * This requires setting the bit in the chunk's free mask corresponding
139 * to the given slot.
140 */
141void
142xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
143{
144 uint slot;
145 xfs_log_item_chunk_t *licp;
146 xfs_log_item_chunk_t **licpp;
147
148 slot = xfs_lic_desc_to_slot(lidp);
149 licp = xfs_lic_desc_to_chunk(lidp);
150 xfs_lic_relse(licp, slot);
151 lidp->lid_item->li_desc = NULL;
152 tp->t_items_free++;
153
154 /*
155 * If there are no more used items in the chunk and this is not
156 * the chunk embedded in the transaction structure, then free
157 * the chunk. First pull it from the chunk list and then
158 * free it back to the heap. We didn't bother with a doubly
159 * linked list here because the lists should be very short
160 * and this is not a performance path. It's better to save
161 * the memory of the extra pointer.
162 *
163 * Also decrement the transaction structure's count of free items
164 * by the number in a chunk since we are freeing an empty chunk.
165 */
166 if (xfs_lic_are_all_free(licp) && (licp != &(tp->t_items))) {
167 licpp = &(tp->t_items.lic_next);
168 while (*licpp != licp) {
169 ASSERT(*licpp != NULL);
170 licpp = &((*licpp)->lic_next);
171 }
172 *licpp = licp->lic_next;
173 kmem_free(licp);
174 tp->t_items_free -= XFS_LIC_NUM_SLOTS;
175 }
176}
177
178/*
179 * This is called to find the descriptor corresponding to the given
180 * log item. It returns a pointer to the descriptor.
181 * The log item MUST have a corresponding descriptor in the given
182 * transaction. This routine does not return NULL, it panics.
183 *
184 * The descriptor pointer is kept in the log item's li_desc field.
185 * Just return it.
186 */
187/*ARGSUSED*/
188xfs_log_item_desc_t *
189xfs_trans_find_item(xfs_trans_t *tp, xfs_log_item_t *lip)
190{
191 ASSERT(lip->li_desc != NULL);
192
193 return lip->li_desc;
194}
195
196
197/*
198 * Return a pointer to the first descriptor in the chunk list.
199 * This does not return NULL if there are none, it panics.
200 *
201 * The first descriptor must be in either the first or second chunk.
202 * This is because the only chunk allowed to be empty is the first.
203 * All others are freed when they become empty.
204 *
205 * At some point this and xfs_trans_next_item() should be optimized
206 * to quickly look at the mask to determine if there is anything to
207 * look at.
208 */
209xfs_log_item_desc_t *
210xfs_trans_first_item(xfs_trans_t *tp)
211{
212 xfs_log_item_chunk_t *licp;
213 int i;
214
215 licp = &tp->t_items;
216 /*
217 * If it's not in the first chunk, skip to the second.
218 */
219 if (xfs_lic_are_all_free(licp)) {
220 licp = licp->lic_next;
221 }
222
223 /*
224 * Return the first non-free descriptor in the chunk.
225 */
226 ASSERT(!xfs_lic_are_all_free(licp));
227 for (i = 0; i < licp->lic_unused; i++) {
228 if (xfs_lic_isfree(licp, i)) {
229 continue;
230 }
231
232 return xfs_lic_slot(licp, i);
233 }
234 cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item");
235 return NULL;
236}
237
238
239/*
240 * Given a descriptor, return the next descriptor in the chunk list.
241 * This returns NULL if there are no more used descriptors in the list.
242 *
243 * We do this by first locating the chunk in which the descriptor resides,
244 * and then scanning forward in the chunk and the list for the next
245 * used descriptor.
246 */
247/*ARGSUSED*/
248xfs_log_item_desc_t *
249xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
250{
251 xfs_log_item_chunk_t *licp;
252 int i;
253
254 licp = xfs_lic_desc_to_chunk(lidp);
255
256 /*
257 * First search the rest of the chunk. The for loop keeps us
258 * from referencing things beyond the end of the chunk.
259 */
260 for (i = (int)xfs_lic_desc_to_slot(lidp) + 1; i < licp->lic_unused; i++) {
261 if (xfs_lic_isfree(licp, i)) {
262 continue;
263 }
264
265 return xfs_lic_slot(licp, i);
266 }
267
268 /*
269 * Now search the next chunk. It must be there, because the
270 * next chunk would have been freed if it were empty.
271 * If there is no next chunk, return NULL.
272 */
273 if (licp->lic_next == NULL) {
274 return NULL;
275 }
276
277 licp = licp->lic_next;
278 ASSERT(!xfs_lic_are_all_free(licp));
279 for (i = 0; i < licp->lic_unused; i++) {
280 if (xfs_lic_isfree(licp, i)) {
281 continue;
282 }
283
284 return xfs_lic_slot(licp, i);
285 }
286 ASSERT(0);
287 /* NOTREACHED */
288 return NULL; /* keep gcc quite */
289}
290
291/*
292 * This is called to unlock all of the items of a transaction and to free
293 * all the descriptors of that transaction.
294 *
295 * It walks the list of descriptors and unlocks each item. It frees
296 * each chunk except that embedded in the transaction as it goes along.
297 */
298void
299xfs_trans_free_items(
300 xfs_trans_t *tp,
301 xfs_lsn_t commit_lsn,
302 int flags)
303{
304 xfs_log_item_chunk_t *licp;
305 xfs_log_item_chunk_t *next_licp;
306 int abort;
307
308 abort = flags & XFS_TRANS_ABORT;
309 licp = &tp->t_items;
310 /*
311 * Special case the embedded chunk so we don't free it below.
312 */
313 if (!xfs_lic_are_all_free(licp)) {
314 (void) xfs_trans_unlock_chunk(licp, 1, abort, commit_lsn);
315 xfs_lic_all_free(licp);
316 licp->lic_unused = 0;
317 }
318 licp = licp->lic_next;
319
320 /*
321 * Unlock each item in each chunk and free the chunks.
322 */
323 while (licp != NULL) {
324 ASSERT(!xfs_lic_are_all_free(licp));
325 (void) xfs_trans_unlock_chunk(licp, 1, abort, commit_lsn);
326 next_licp = licp->lic_next;
327 kmem_free(licp);
328 licp = next_licp;
329 }
330
331 /*
332 * Reset the transaction structure's free item count.
333 */
334 tp->t_items_free = XFS_LIC_NUM_SLOTS;
335 tp->t_items.lic_next = NULL;
336}
337
338
339
340/*
341 * This is called to unlock the items associated with a transaction.
342 * Items which were not logged should be freed.
343 * Those which were logged must still be tracked so they can be unpinned
344 * when the transaction commits.
345 */
346void
347xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
348{
349 xfs_log_item_chunk_t *licp;
350 xfs_log_item_chunk_t *next_licp;
351 xfs_log_item_chunk_t **licpp;
352 int freed;
353
354 freed = 0;
355 licp = &tp->t_items;
356
357 /*
358 * Special case the embedded chunk so we don't free.
359 */
360 if (!xfs_lic_are_all_free(licp)) {
361 freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
362 }
363 licpp = &(tp->t_items.lic_next);
364 licp = licp->lic_next;
365
366 /*
367 * Unlock each item in each chunk, free non-dirty descriptors,
368 * and free empty chunks.
369 */
370 while (licp != NULL) {
371 ASSERT(!xfs_lic_are_all_free(licp));
372 freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
373 next_licp = licp->lic_next;
374 if (xfs_lic_are_all_free(licp)) {
375 *licpp = next_licp;
376 kmem_free(licp);
377 freed -= XFS_LIC_NUM_SLOTS;
378 } else {
379 licpp = &(licp->lic_next);
380 }
381 ASSERT(*licpp == next_licp);
382 licp = next_licp;
383 }
384
385 /*
386 * Fix the free descriptor count in the transaction.
387 */
388 tp->t_items_free += freed;
389}
390
391/*
392 * Unlock each item pointed to by a descriptor in the given chunk.
393 * Stamp the commit lsn into each item if necessary.
394 * Free descriptors pointing to items which are not dirty if freeing_chunk
395 * is zero. If freeing_chunk is non-zero, then we need to unlock all
396 * items in the chunk.
397 *
398 * Return the number of descriptors freed.
399 */
400STATIC int
401xfs_trans_unlock_chunk(
402 xfs_log_item_chunk_t *licp,
403 int freeing_chunk,
404 int abort,
405 xfs_lsn_t commit_lsn)
406{
407 xfs_log_item_desc_t *lidp;
408 xfs_log_item_t *lip;
409 int i;
410 int freed;
411
412 freed = 0;
413 lidp = licp->lic_descs;
414 for (i = 0; i < licp->lic_unused; i++, lidp++) {
415 if (xfs_lic_isfree(licp, i)) {
416 continue;
417 }
418 lip = lidp->lid_item;
419 lip->li_desc = NULL;
420
421 if (commit_lsn != NULLCOMMITLSN)
422 IOP_COMMITTING(lip, commit_lsn);
423 if (abort)
424 lip->li_flags |= XFS_LI_ABORTED;
425 IOP_UNLOCK(lip);
426
427 /*
428 * Free the descriptor if the item is not dirty
429 * within this transaction and the caller is not
430 * going to just free the entire thing regardless.
431 */
432 if (!(freeing_chunk) &&
433 (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) {
434 xfs_lic_relse(licp, i);
435 freed++;
436 }
437 }
438
439 return freed;
440}
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index c6e4f2c8de6e..e2d93d8ead7b 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -23,22 +23,8 @@ struct xfs_log_item_desc;
23struct xfs_mount; 23struct xfs_mount;
24struct xfs_trans; 24struct xfs_trans;
25 25
26/* 26void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
27 * From xfs_trans_item.c 27void xfs_trans_del_item(struct xfs_log_item *);
28 */
29struct xfs_log_item_desc *xfs_trans_add_item(struct xfs_trans *,
30 struct xfs_log_item *);
31void xfs_trans_free_item(struct xfs_trans *,
32 struct xfs_log_item_desc *);
33struct xfs_log_item_desc *xfs_trans_find_item(struct xfs_trans *,
34 struct xfs_log_item *);
35struct xfs_log_item_desc *xfs_trans_first_item(struct xfs_trans *);
36struct xfs_log_item_desc *xfs_trans_next_item(struct xfs_trans *,
37 struct xfs_log_item_desc *);
38
39void xfs_trans_unlock_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn);
40void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn,
41 int flags);
42 28
43void xfs_trans_item_committed(struct xfs_log_item *lip, 29void xfs_trans_item_committed(struct xfs_log_item *lip,
44 xfs_lsn_t commit_lsn, int aborted); 30 xfs_lsn_t commit_lsn, int aborted);