aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans.c
diff options
context:
space:
mode:
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);