diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 211 |
1 files changed, 134 insertions, 77 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 28547dfce037..fdca7416c754 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 |
@@ -24,16 +25,12 @@ | |||
24 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 29 | #include "xfs_error.h" |
31 | #include "xfs_da_btree.h" | 30 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | ||
37 | #include "xfs_dinode.h" | 34 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 35 | #include "xfs_inode.h" |
39 | #include "xfs_btree.h" | 36 | #include "xfs_btree.h" |
@@ -47,6 +44,7 @@ | |||
47 | #include "xfs_trace.h" | 44 | #include "xfs_trace.h" |
48 | 45 | ||
49 | kmem_zone_t *xfs_trans_zone; | 46 | kmem_zone_t *xfs_trans_zone; |
47 | kmem_zone_t *xfs_log_item_desc_zone; | ||
50 | 48 | ||
51 | 49 | ||
52 | /* | 50 | /* |
@@ -597,8 +595,7 @@ _xfs_trans_alloc( | |||
597 | tp->t_magic = XFS_TRANS_MAGIC; | 595 | tp->t_magic = XFS_TRANS_MAGIC; |
598 | tp->t_type = type; | 596 | tp->t_type = type; |
599 | tp->t_mountp = mp; | 597 | tp->t_mountp = mp; |
600 | tp->t_items_free = XFS_LIC_NUM_SLOTS; | 598 | INIT_LIST_HEAD(&tp->t_items); |
601 | xfs_lic_init(&(tp->t_items)); | ||
602 | INIT_LIST_HEAD(&tp->t_busy); | 599 | INIT_LIST_HEAD(&tp->t_busy); |
603 | return tp; | 600 | return tp; |
604 | } | 601 | } |
@@ -643,8 +640,7 @@ xfs_trans_dup( | |||
643 | ntp->t_magic = XFS_TRANS_MAGIC; | 640 | ntp->t_magic = XFS_TRANS_MAGIC; |
644 | ntp->t_type = tp->t_type; | 641 | ntp->t_type = tp->t_type; |
645 | ntp->t_mountp = tp->t_mountp; | 642 | ntp->t_mountp = tp->t_mountp; |
646 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; | 643 | INIT_LIST_HEAD(&ntp->t_items); |
647 | xfs_lic_init(&(ntp->t_items)); | ||
648 | INIT_LIST_HEAD(&ntp->t_busy); | 644 | INIT_LIST_HEAD(&ntp->t_busy); |
649 | 645 | ||
650 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 646 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
@@ -1124,6 +1120,108 @@ xfs_trans_unreserve_and_mod_sb( | |||
1124 | } | 1120 | } |
1125 | 1121 | ||
1126 | /* | 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 | */ | ||
1127 | void | ||
1128 | xfs_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 | KM_NOFS); | ||
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 | |||
1147 | STATIC void | ||
1148 | xfs_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 | */ | ||
1158 | void | ||
1159 | xfs_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 | */ | ||
1170 | STATIC void | ||
1171 | xfs_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 | */ | ||
1199 | STATIC void | ||
1200 | xfs_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 | /* | ||
1127 | * Total up the number of log iovecs needed to commit this | 1225 | * Total up the number of log iovecs needed to commit this |
1128 | * transaction. The transaction itself needs one for the | 1226 | * transaction. The transaction itself needs one for the |
1129 | * transaction header. Ask each dirty item in turn how many | 1227 | * transaction header. Ask each dirty item in turn how many |
@@ -1134,30 +1232,27 @@ xfs_trans_count_vecs( | |||
1134 | struct xfs_trans *tp) | 1232 | struct xfs_trans *tp) |
1135 | { | 1233 | { |
1136 | int nvecs; | 1234 | int nvecs; |
1137 | xfs_log_item_desc_t *lidp; | 1235 | struct xfs_log_item_desc *lidp; |
1138 | 1236 | ||
1139 | nvecs = 1; | 1237 | nvecs = 1; |
1140 | lidp = xfs_trans_first_item(tp); | ||
1141 | ASSERT(lidp != NULL); | ||
1142 | 1238 | ||
1143 | /* 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 |
1144 | * 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 |
1145 | * deal with it. | 1241 | * deal with it. |
1146 | */ | 1242 | */ |
1147 | if (lidp == NULL) | 1243 | if (list_empty(&tp->t_items)) { |
1244 | ASSERT(0); | ||
1148 | return 0; | 1245 | return 0; |
1246 | } | ||
1149 | 1247 | ||
1150 | while (lidp != NULL) { | 1248 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1151 | /* | 1249 | /* |
1152 | * Skip items which aren't dirty in this transaction. | 1250 | * Skip items which aren't dirty in this transaction. |
1153 | */ | 1251 | */ |
1154 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1252 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1155 | lidp = xfs_trans_next_item(tp, lidp); | ||
1156 | continue; | 1253 | continue; |
1157 | } | ||
1158 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | 1254 | lidp->lid_size = IOP_SIZE(lidp->lid_item); |
1159 | nvecs += lidp->lid_size; | 1255 | nvecs += lidp->lid_size; |
1160 | lidp = xfs_trans_next_item(tp, lidp); | ||
1161 | } | 1256 | } |
1162 | 1257 | ||
1163 | return nvecs; | 1258 | return nvecs; |
@@ -1177,7 +1272,7 @@ xfs_trans_fill_vecs( | |||
1177 | struct xfs_trans *tp, | 1272 | struct xfs_trans *tp, |
1178 | struct xfs_log_iovec *log_vector) | 1273 | struct xfs_log_iovec *log_vector) |
1179 | { | 1274 | { |
1180 | xfs_log_item_desc_t *lidp; | 1275 | struct xfs_log_item_desc *lidp; |
1181 | struct xfs_log_iovec *vecp; | 1276 | struct xfs_log_iovec *vecp; |
1182 | uint nitems; | 1277 | uint nitems; |
1183 | 1278 | ||
@@ -1188,14 +1283,11 @@ xfs_trans_fill_vecs( | |||
1188 | vecp = log_vector + 1; | 1283 | vecp = log_vector + 1; |
1189 | 1284 | ||
1190 | nitems = 0; | 1285 | nitems = 0; |
1191 | lidp = xfs_trans_first_item(tp); | 1286 | ASSERT(!list_empty(&tp->t_items)); |
1192 | ASSERT(lidp); | 1287 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1193 | while (lidp) { | ||
1194 | /* Skip items which aren't dirty in this transaction. */ | 1288 | /* Skip items which aren't dirty in this transaction. */ |
1195 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1289 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1196 | lidp = xfs_trans_next_item(tp, lidp); | ||
1197 | continue; | 1290 | continue; |
1198 | } | ||
1199 | 1291 | ||
1200 | /* | 1292 | /* |
1201 | * 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 |
@@ -1206,7 +1298,6 @@ xfs_trans_fill_vecs( | |||
1206 | IOP_FORMAT(lidp->lid_item, vecp); | 1298 | IOP_FORMAT(lidp->lid_item, vecp); |
1207 | vecp += lidp->lid_size; | 1299 | vecp += lidp->lid_size; |
1208 | IOP_PIN(lidp->lid_item); | 1300 | IOP_PIN(lidp->lid_item); |
1209 | lidp = xfs_trans_next_item(tp, lidp); | ||
1210 | } | 1301 | } |
1211 | 1302 | ||
1212 | /* | 1303 | /* |
@@ -1284,7 +1375,7 @@ xfs_trans_item_committed( | |||
1284 | * log item flags, if anyone else stales the buffer we do not want to | 1375 | * log item flags, if anyone else stales the buffer we do not want to |
1285 | * pay any attention to it. | 1376 | * pay any attention to it. |
1286 | */ | 1377 | */ |
1287 | IOP_UNPIN(lip); | 1378 | IOP_UNPIN(lip, 0); |
1288 | } | 1379 | } |
1289 | 1380 | ||
1290 | /* | 1381 | /* |
@@ -1301,24 +1392,15 @@ xfs_trans_committed( | |||
1301 | struct xfs_trans *tp, | 1392 | struct xfs_trans *tp, |
1302 | int abortflag) | 1393 | int abortflag) |
1303 | { | 1394 | { |
1304 | xfs_log_item_desc_t *lidp; | 1395 | struct xfs_log_item_desc *lidp, *next; |
1305 | xfs_log_item_chunk_t *licp; | ||
1306 | xfs_log_item_chunk_t *next_licp; | ||
1307 | 1396 | ||
1308 | /* Call the transaction's completion callback if there is one. */ | 1397 | /* Call the transaction's completion callback if there is one. */ |
1309 | if (tp->t_callback != NULL) | 1398 | if (tp->t_callback != NULL) |
1310 | tp->t_callback(tp, tp->t_callarg); | 1399 | tp->t_callback(tp, tp->t_callarg); |
1311 | 1400 | ||
1312 | for (lidp = xfs_trans_first_item(tp); | 1401 | list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { |
1313 | lidp != NULL; | ||
1314 | lidp = xfs_trans_next_item(tp, lidp)) { | ||
1315 | xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag); | 1402 | xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag); |
1316 | } | 1403 | xfs_trans_free_item_desc(lidp); |
1317 | |||
1318 | /* free the item chunks, ignoring the embedded chunk */ | ||
1319 | for (licp = tp->t_items.lic_next; licp != NULL; licp = next_licp) { | ||
1320 | next_licp = licp->lic_next; | ||
1321 | kmem_free(licp); | ||
1322 | } | 1404 | } |
1323 | 1405 | ||
1324 | xfs_trans_free(tp); | 1406 | xfs_trans_free(tp); |
@@ -1333,16 +1415,14 @@ xfs_trans_uncommit( | |||
1333 | struct xfs_trans *tp, | 1415 | struct xfs_trans *tp, |
1334 | uint flags) | 1416 | uint flags) |
1335 | { | 1417 | { |
1336 | xfs_log_item_desc_t *lidp; | 1418 | struct xfs_log_item_desc *lidp; |
1337 | 1419 | ||
1338 | for (lidp = xfs_trans_first_item(tp); | 1420 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1339 | lidp != NULL; | ||
1340 | lidp = xfs_trans_next_item(tp, lidp)) { | ||
1341 | /* | 1421 | /* |
1342 | * Unpin all but those that aren't dirty. | 1422 | * Unpin all but those that aren't dirty. |
1343 | */ | 1423 | */ |
1344 | if (lidp->lid_flags & XFS_LID_DIRTY) | 1424 | if (lidp->lid_flags & XFS_LID_DIRTY) |
1345 | IOP_UNPIN_REMOVE(lidp->lid_item, tp); | 1425 | IOP_UNPIN(lidp->lid_item, 1); |
1346 | } | 1426 | } |
1347 | 1427 | ||
1348 | xfs_trans_unreserve_and_mod_sb(tp); | 1428 | xfs_trans_unreserve_and_mod_sb(tp); |
@@ -1508,33 +1588,28 @@ STATIC struct xfs_log_vec * | |||
1508 | xfs_trans_alloc_log_vecs( | 1588 | xfs_trans_alloc_log_vecs( |
1509 | xfs_trans_t *tp) | 1589 | xfs_trans_t *tp) |
1510 | { | 1590 | { |
1511 | xfs_log_item_desc_t *lidp; | 1591 | struct xfs_log_item_desc *lidp; |
1512 | struct xfs_log_vec *lv = NULL; | 1592 | struct xfs_log_vec *lv = NULL; |
1513 | struct xfs_log_vec *ret_lv = NULL; | 1593 | struct xfs_log_vec *ret_lv = NULL; |
1514 | 1594 | ||
1515 | lidp = xfs_trans_first_item(tp); | ||
1516 | 1595 | ||
1517 | /* Bail out if we didn't find a log item. */ | 1596 | /* Bail out if we didn't find a log item. */ |
1518 | if (!lidp) { | 1597 | if (list_empty(&tp->t_items)) { |
1519 | ASSERT(0); | 1598 | ASSERT(0); |
1520 | return NULL; | 1599 | return NULL; |
1521 | } | 1600 | } |
1522 | 1601 | ||
1523 | while (lidp != NULL) { | 1602 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1524 | struct xfs_log_vec *new_lv; | 1603 | struct xfs_log_vec *new_lv; |
1525 | 1604 | ||
1526 | /* Skip items which aren't dirty in this transaction. */ | 1605 | /* Skip items which aren't dirty in this transaction. */ |
1527 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1606 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1528 | lidp = xfs_trans_next_item(tp, lidp); | ||
1529 | continue; | 1607 | continue; |
1530 | } | ||
1531 | 1608 | ||
1532 | /* Skip items that do not have any vectors for writing */ | 1609 | /* Skip items that do not have any vectors for writing */ |
1533 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | 1610 | lidp->lid_size = IOP_SIZE(lidp->lid_item); |
1534 | if (!lidp->lid_size) { | 1611 | if (!lidp->lid_size) |
1535 | lidp = xfs_trans_next_item(tp, lidp); | ||
1536 | continue; | 1612 | continue; |
1537 | } | ||
1538 | 1613 | ||
1539 | new_lv = kmem_zalloc(sizeof(*new_lv) + | 1614 | new_lv = kmem_zalloc(sizeof(*new_lv) + |
1540 | lidp->lid_size * sizeof(struct xfs_log_iovec), | 1615 | lidp->lid_size * sizeof(struct xfs_log_iovec), |
@@ -1549,7 +1624,6 @@ xfs_trans_alloc_log_vecs( | |||
1549 | else | 1624 | else |
1550 | lv->lv_next = new_lv; | 1625 | lv->lv_next = new_lv; |
1551 | lv = new_lv; | 1626 | lv = new_lv; |
1552 | lidp = xfs_trans_next_item(tp, lidp); | ||
1553 | } | 1627 | } |
1554 | 1628 | ||
1555 | return ret_lv; | 1629 | return ret_lv; |
@@ -1708,12 +1782,6 @@ xfs_trans_cancel( | |||
1708 | int flags) | 1782 | int flags) |
1709 | { | 1783 | { |
1710 | int log_flags; | 1784 | int log_flags; |
1711 | #ifdef DEBUG | ||
1712 | xfs_log_item_chunk_t *licp; | ||
1713 | xfs_log_item_desc_t *lidp; | ||
1714 | xfs_log_item_t *lip; | ||
1715 | int i; | ||
1716 | #endif | ||
1717 | xfs_mount_t *mp = tp->t_mountp; | 1785 | xfs_mount_t *mp = tp->t_mountp; |
1718 | 1786 | ||
1719 | /* | 1787 | /* |
@@ -1732,21 +1800,11 @@ xfs_trans_cancel( | |||
1732 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | 1800 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
1733 | } | 1801 | } |
1734 | #ifdef DEBUG | 1802 | #ifdef DEBUG |
1735 | if (!(flags & XFS_TRANS_ABORT)) { | 1803 | if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) { |
1736 | licp = &(tp->t_items); | 1804 | struct xfs_log_item_desc *lidp; |
1737 | while (licp != NULL) { | 1805 | |
1738 | lidp = licp->lic_descs; | 1806 | list_for_each_entry(lidp, &tp->t_items, lid_trans) |
1739 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | 1807 | ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD)); |
1740 | if (xfs_lic_isfree(licp, i)) { | ||
1741 | continue; | ||
1742 | } | ||
1743 | |||
1744 | lip = lidp->lid_item; | ||
1745 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
1746 | ASSERT(!(lip->li_type == XFS_LI_EFD)); | ||
1747 | } | ||
1748 | licp = licp->lic_next; | ||
1749 | } | ||
1750 | } | 1808 | } |
1751 | #endif | 1809 | #endif |
1752 | xfs_trans_unreserve_and_mod_sb(tp); | 1810 | xfs_trans_unreserve_and_mod_sb(tp); |
@@ -1834,7 +1892,6 @@ xfs_trans_roll( | |||
1834 | if (error) | 1892 | if (error) |
1835 | return error; | 1893 | return error; |
1836 | 1894 | ||
1837 | xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); | 1895 | xfs_trans_ijoin(trans, dp); |
1838 | xfs_trans_ihold(trans, dp); | ||
1839 | return 0; | 1896 | return 0; |
1840 | } | 1897 | } |