diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index e4ebddd3c500..d98758a09677 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 *); |
@@ -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(). |