aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans.c
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/xfs_trans.c
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/xfs_trans.c')
-rw-r--r--fs/xfs/xfs_trans.c200
1 files changed, 131 insertions, 69 deletions
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);