aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 a5239b1713b..0dce969d6ca 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 5593066d497..4b90e4b531b 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 08f5604d092..7de91d1b75c 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 ed4e3ae2c1d..ff8675b4197 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 91ad92e83bc..711f69abbbe 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 1023b1fadfe..8d0e543ca3c 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 57c53f7ad2c..9c41efccf72 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 e639e8e9a2a..0c903eb8bbe 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 d1d08aa404b..74a1c33e409 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 dfb6a0fdcf9..f783d5e9fa7 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 04cc08a1b66..865eeb63ce1 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 55035a7401c..00000000000
--- 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 c6e4f2c8de6..e2d93d8ead7 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);