diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 103 |
1 files changed, 97 insertions, 6 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 40d9595a8de2..ce558efa2ea0 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -655,7 +655,7 @@ xfs_trans_apply_sb_deltas( | |||
655 | * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we | 655 | * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we |
656 | * still need to update the incore superblock with the changes. | 656 | * still need to update the incore superblock with the changes. |
657 | */ | 657 | */ |
658 | STATIC void | 658 | void |
659 | xfs_trans_unreserve_and_mod_sb( | 659 | xfs_trans_unreserve_and_mod_sb( |
660 | xfs_trans_t *tp) | 660 | xfs_trans_t *tp) |
661 | { | 661 | { |
@@ -883,7 +883,7 @@ xfs_trans_fill_vecs( | |||
883 | * they could be immediately flushed and we'd have to race with the flusher | 883 | * they could be immediately flushed and we'd have to race with the flusher |
884 | * trying to pull the item from the AIL as we add it. | 884 | * trying to pull the item from the AIL as we add it. |
885 | */ | 885 | */ |
886 | static void | 886 | void |
887 | xfs_trans_item_committed( | 887 | xfs_trans_item_committed( |
888 | struct xfs_log_item *lip, | 888 | struct xfs_log_item *lip, |
889 | xfs_lsn_t commit_lsn, | 889 | xfs_lsn_t commit_lsn, |
@@ -994,7 +994,7 @@ xfs_trans_uncommit( | |||
994 | xfs_trans_unreserve_and_mod_sb(tp); | 994 | xfs_trans_unreserve_and_mod_sb(tp); |
995 | xfs_trans_unreserve_and_mod_dquots(tp); | 995 | xfs_trans_unreserve_and_mod_dquots(tp); |
996 | 996 | ||
997 | xfs_trans_free_items(tp, flags); | 997 | xfs_trans_free_items(tp, NULLCOMMITLSN, flags); |
998 | xfs_trans_free(tp); | 998 | xfs_trans_free(tp); |
999 | } | 999 | } |
1000 | 1000 | ||
@@ -1144,6 +1144,93 @@ xfs_trans_commit_iclog( | |||
1144 | return xfs_log_release_iclog(mp, commit_iclog); | 1144 | return xfs_log_release_iclog(mp, commit_iclog); |
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | /* | ||
1148 | * Walk the log items and allocate log vector structures for | ||
1149 | * each item large enough to fit all the vectors they require. | ||
1150 | * Note that this format differs from the old log vector format in | ||
1151 | * that there is no transaction header in these log vectors. | ||
1152 | */ | ||
1153 | STATIC struct xfs_log_vec * | ||
1154 | xfs_trans_alloc_log_vecs( | ||
1155 | xfs_trans_t *tp) | ||
1156 | { | ||
1157 | xfs_log_item_desc_t *lidp; | ||
1158 | struct xfs_log_vec *lv = NULL; | ||
1159 | struct xfs_log_vec *ret_lv = NULL; | ||
1160 | |||
1161 | lidp = xfs_trans_first_item(tp); | ||
1162 | |||
1163 | /* Bail out if we didn't find a log item. */ | ||
1164 | if (!lidp) { | ||
1165 | ASSERT(0); | ||
1166 | return NULL; | ||
1167 | } | ||
1168 | |||
1169 | while (lidp != NULL) { | ||
1170 | struct xfs_log_vec *new_lv; | ||
1171 | |||
1172 | /* Skip items which aren't dirty in this transaction. */ | ||
1173 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
1174 | lidp = xfs_trans_next_item(tp, lidp); | ||
1175 | continue; | ||
1176 | } | ||
1177 | |||
1178 | /* Skip items that do not have any vectors for writing */ | ||
1179 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | ||
1180 | if (!lidp->lid_size) { | ||
1181 | lidp = xfs_trans_next_item(tp, lidp); | ||
1182 | continue; | ||
1183 | } | ||
1184 | |||
1185 | new_lv = kmem_zalloc(sizeof(*new_lv) + | ||
1186 | lidp->lid_size * sizeof(struct xfs_log_iovec), | ||
1187 | KM_SLEEP); | ||
1188 | |||
1189 | /* The allocated iovec region lies beyond the log vector. */ | ||
1190 | new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1]; | ||
1191 | new_lv->lv_niovecs = lidp->lid_size; | ||
1192 | new_lv->lv_item = lidp->lid_item; | ||
1193 | if (!ret_lv) | ||
1194 | ret_lv = new_lv; | ||
1195 | else | ||
1196 | lv->lv_next = new_lv; | ||
1197 | lv = new_lv; | ||
1198 | lidp = xfs_trans_next_item(tp, lidp); | ||
1199 | } | ||
1200 | |||
1201 | return ret_lv; | ||
1202 | } | ||
1203 | |||
1204 | static int | ||
1205 | xfs_trans_commit_cil( | ||
1206 | struct xfs_mount *mp, | ||
1207 | struct xfs_trans *tp, | ||
1208 | xfs_lsn_t *commit_lsn, | ||
1209 | int flags) | ||
1210 | { | ||
1211 | struct xfs_log_vec *log_vector; | ||
1212 | int error; | ||
1213 | |||
1214 | /* | ||
1215 | * Get each log item to allocate a vector structure for | ||
1216 | * the log item to to pass to the log write code. The | ||
1217 | * CIL commit code will format the vector and save it away. | ||
1218 | */ | ||
1219 | log_vector = xfs_trans_alloc_log_vecs(tp); | ||
1220 | if (!log_vector) | ||
1221 | return ENOMEM; | ||
1222 | |||
1223 | error = xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); | ||
1224 | if (error) | ||
1225 | return error; | ||
1226 | |||
1227 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | ||
1228 | |||
1229 | /* xfs_trans_free_items() unlocks them first */ | ||
1230 | xfs_trans_free_items(tp, *commit_lsn, 0); | ||
1231 | xfs_trans_free(tp); | ||
1232 | return 0; | ||
1233 | } | ||
1147 | 1234 | ||
1148 | /* | 1235 | /* |
1149 | * xfs_trans_commit | 1236 | * xfs_trans_commit |
@@ -1204,7 +1291,11 @@ _xfs_trans_commit( | |||
1204 | xfs_trans_apply_sb_deltas(tp); | 1291 | xfs_trans_apply_sb_deltas(tp); |
1205 | xfs_trans_apply_dquot_deltas(tp); | 1292 | xfs_trans_apply_dquot_deltas(tp); |
1206 | 1293 | ||
1207 | error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags); | 1294 | if (mp->m_flags & XFS_MOUNT_DELAYLOG) |
1295 | error = xfs_trans_commit_cil(mp, tp, &commit_lsn, flags); | ||
1296 | else | ||
1297 | error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags); | ||
1298 | |||
1208 | if (error == ENOMEM) { | 1299 | if (error == ENOMEM) { |
1209 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 1300 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1210 | error = XFS_ERROR(EIO); | 1301 | error = XFS_ERROR(EIO); |
@@ -1242,7 +1333,7 @@ out_unreserve: | |||
1242 | error = XFS_ERROR(EIO); | 1333 | error = XFS_ERROR(EIO); |
1243 | } | 1334 | } |
1244 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 1335 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
1245 | xfs_trans_free_items(tp, error ? XFS_TRANS_ABORT : 0); | 1336 | xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0); |
1246 | xfs_trans_free(tp); | 1337 | xfs_trans_free(tp); |
1247 | 1338 | ||
1248 | XFS_STATS_INC(xs_trans_empty); | 1339 | XFS_STATS_INC(xs_trans_empty); |
@@ -1320,7 +1411,7 @@ xfs_trans_cancel( | |||
1320 | /* mark this thread as no longer being in a transaction */ | 1411 | /* mark this thread as no longer being in a transaction */ |
1321 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 1412 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
1322 | 1413 | ||
1323 | xfs_trans_free_items(tp, flags); | 1414 | xfs_trans_free_items(tp, NULLCOMMITLSN, flags); |
1324 | xfs_trans_free(tp); | 1415 | xfs_trans_free(tp); |
1325 | } | 1416 | } |
1326 | 1417 | ||