diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index e4ebddd3c500..4e1c22a23be5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "xfs_quota.h" | 43 | #include "xfs_quota.h" |
44 | #include "xfs_trans_priv.h" | 44 | #include "xfs_trans_priv.h" |
45 | #include "xfs_trans_space.h" | 45 | #include "xfs_trans_space.h" |
46 | #include "xfs_inode_item.h" | ||
46 | 47 | ||
47 | 48 | ||
48 | STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); | 49 | STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); |
@@ -253,7 +254,7 @@ _xfs_trans_alloc( | |||
253 | tp->t_mountp = mp; | 254 | tp->t_mountp = mp; |
254 | tp->t_items_free = XFS_LIC_NUM_SLOTS; | 255 | tp->t_items_free = XFS_LIC_NUM_SLOTS; |
255 | tp->t_busy_free = XFS_LBC_NUM_SLOTS; | 256 | tp->t_busy_free = XFS_LBC_NUM_SLOTS; |
256 | XFS_LIC_INIT(&(tp->t_items)); | 257 | xfs_lic_init(&(tp->t_items)); |
257 | XFS_LBC_INIT(&(tp->t_busy)); | 258 | XFS_LBC_INIT(&(tp->t_busy)); |
258 | return tp; | 259 | return tp; |
259 | } | 260 | } |
@@ -282,7 +283,7 @@ xfs_trans_dup( | |||
282 | ntp->t_mountp = tp->t_mountp; | 283 | ntp->t_mountp = tp->t_mountp; |
283 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; | 284 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; |
284 | ntp->t_busy_free = XFS_LBC_NUM_SLOTS; | 285 | ntp->t_busy_free = XFS_LBC_NUM_SLOTS; |
285 | XFS_LIC_INIT(&(ntp->t_items)); | 286 | xfs_lic_init(&(ntp->t_items)); |
286 | XFS_LBC_INIT(&(ntp->t_busy)); | 287 | XFS_LBC_INIT(&(ntp->t_busy)); |
287 | 288 | ||
288 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 289 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
@@ -1169,7 +1170,7 @@ xfs_trans_cancel( | |||
1169 | while (licp != NULL) { | 1170 | while (licp != NULL) { |
1170 | lidp = licp->lic_descs; | 1171 | lidp = licp->lic_descs; |
1171 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | 1172 | for (i = 0; i < licp->lic_unused; i++, lidp++) { |
1172 | if (XFS_LIC_ISFREE(licp, i)) { | 1173 | if (xfs_lic_isfree(licp, i)) { |
1173 | continue; | 1174 | continue; |
1174 | } | 1175 | } |
1175 | 1176 | ||
@@ -1216,6 +1217,68 @@ xfs_trans_free( | |||
1216 | kmem_zone_free(xfs_trans_zone, tp); | 1217 | kmem_zone_free(xfs_trans_zone, tp); |
1217 | } | 1218 | } |
1218 | 1219 | ||
1220 | /* | ||
1221 | * Roll from one trans in the sequence of PERMANENT transactions to | ||
1222 | * the next: permanent transactions are only flushed out when | ||
1223 | * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon | ||
1224 | * as possible to let chunks of it go to the log. So we commit the | ||
1225 | * chunk we've been working on and get a new transaction to continue. | ||
1226 | */ | ||
1227 | int | ||
1228 | xfs_trans_roll( | ||
1229 | struct xfs_trans **tpp, | ||
1230 | struct xfs_inode *dp) | ||
1231 | { | ||
1232 | struct xfs_trans *trans; | ||
1233 | unsigned int logres, count; | ||
1234 | int error; | ||
1235 | |||
1236 | /* | ||
1237 | * Ensure that the inode is always logged. | ||
1238 | */ | ||
1239 | trans = *tpp; | ||
1240 | xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); | ||
1241 | |||
1242 | /* | ||
1243 | * Copy the critical parameters from one trans to the next. | ||
1244 | */ | ||
1245 | logres = trans->t_log_res; | ||
1246 | count = trans->t_log_count; | ||
1247 | *tpp = xfs_trans_dup(trans); | ||
1248 | |||
1249 | /* | ||
1250 | * Commit the current transaction. | ||
1251 | * If this commit failed, then it'd just unlock those items that | ||
1252 | * are not marked ihold. That also means that a filesystem shutdown | ||
1253 | * is in progress. The caller takes the responsibility to cancel | ||
1254 | * the duplicate transaction that gets returned. | ||
1255 | */ | ||
1256 | error = xfs_trans_commit(trans, 0); | ||
1257 | if (error) | ||
1258 | return (error); | ||
1259 | |||
1260 | trans = *tpp; | ||
1261 | |||
1262 | /* | ||
1263 | * Reserve space in the log for th next transaction. | ||
1264 | * This also pushes items in the "AIL", the list of logged items, | ||
1265 | * out to disk if they are taking up space at the tail of the log | ||
1266 | * that we want to use. This requires that either nothing be locked | ||
1267 | * across this call, or that anything that is locked be logged in | ||
1268 | * the prior and the next transactions. | ||
1269 | */ | ||
1270 | error = xfs_trans_reserve(trans, 0, logres, 0, | ||
1271 | XFS_TRANS_PERM_LOG_RES, count); | ||
1272 | /* | ||
1273 | * Ensure that the inode is in the new transaction and locked. | ||
1274 | */ | ||
1275 | if (error) | ||
1276 | return error; | ||
1277 | |||
1278 | xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); | ||
1279 | xfs_trans_ihold(trans, dp); | ||
1280 | return 0; | ||
1281 | } | ||
1219 | 1282 | ||
1220 | /* | 1283 | /* |
1221 | * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item(). | 1284 | * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item(). |
@@ -1253,7 +1316,7 @@ xfs_trans_committed( | |||
1253 | * Special case the chunk embedded in the transaction. | 1316 | * Special case the chunk embedded in the transaction. |
1254 | */ | 1317 | */ |
1255 | licp = &(tp->t_items); | 1318 | licp = &(tp->t_items); |
1256 | if (!(XFS_LIC_ARE_ALL_FREE(licp))) { | 1319 | if (!(xfs_lic_are_all_free(licp))) { |
1257 | xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); | 1320 | xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); |
1258 | } | 1321 | } |
1259 | 1322 | ||
@@ -1262,7 +1325,7 @@ xfs_trans_committed( | |||
1262 | */ | 1325 | */ |
1263 | licp = licp->lic_next; | 1326 | licp = licp->lic_next; |
1264 | while (licp != NULL) { | 1327 | while (licp != NULL) { |
1265 | ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); | 1328 | ASSERT(!xfs_lic_are_all_free(licp)); |
1266 | xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); | 1329 | xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); |
1267 | next_licp = licp->lic_next; | 1330 | next_licp = licp->lic_next; |
1268 | kmem_free(licp); | 1331 | kmem_free(licp); |
@@ -1325,7 +1388,7 @@ xfs_trans_chunk_committed( | |||
1325 | 1388 | ||
1326 | lidp = licp->lic_descs; | 1389 | lidp = licp->lic_descs; |
1327 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | 1390 | for (i = 0; i < licp->lic_unused; i++, lidp++) { |
1328 | if (XFS_LIC_ISFREE(licp, i)) { | 1391 | if (xfs_lic_isfree(licp, i)) { |
1329 | continue; | 1392 | continue; |
1330 | } | 1393 | } |
1331 | 1394 | ||