diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-12-03 19:43:01 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-12-17 13:51:23 -0500 |
commit | e8aed3450c0afd6fdb79ec233f806e3e69454dfe (patch) | |
tree | aa83824230c1b0c58fe9ec68d007c35f42b90fa7 | |
parent | 0879c584ffcccd50a8d0f72cab3a51702613f901 (diff) |
ocfs2: Re-journal buffers after transaction extend
ocfs2_extend_trans() might call journal_restart() which will commit dirty
buffers and then restart the transaction. This means that any buffers which
still need changes should be passed to journal_access() again. Some paths
during extend weren't doing this right.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
-rw-r--r-- | fs/ocfs2/alloc.c | 66 | ||||
-rw-r--r-- | fs/ocfs2/journal.c | 6 |
2 files changed, 51 insertions, 21 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 97f0db5167c4..23c8cda43f19 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -2389,6 +2389,18 @@ static int __ocfs2_rotate_tree_left(struct inode *inode, | |||
2389 | goto out; | 2389 | goto out; |
2390 | } | 2390 | } |
2391 | 2391 | ||
2392 | /* | ||
2393 | * Caller might still want to make changes to the | ||
2394 | * tree root, so re-add it to the journal here. | ||
2395 | */ | ||
2396 | ret = ocfs2_journal_access(handle, inode, | ||
2397 | path_root_bh(left_path), | ||
2398 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2399 | if (ret) { | ||
2400 | mlog_errno(ret); | ||
2401 | goto out; | ||
2402 | } | ||
2403 | |||
2392 | ret = ocfs2_rotate_subtree_left(inode, handle, left_path, | 2404 | ret = ocfs2_rotate_subtree_left(inode, handle, left_path, |
2393 | right_path, subtree_root, | 2405 | right_path, subtree_root, |
2394 | dealloc, &deleted); | 2406 | dealloc, &deleted); |
@@ -3289,16 +3301,6 @@ static int ocfs2_insert_path(struct inode *inode, | |||
3289 | int ret, subtree_index; | 3301 | int ret, subtree_index; |
3290 | struct buffer_head *leaf_bh = path_leaf_bh(right_path); | 3302 | struct buffer_head *leaf_bh = path_leaf_bh(right_path); |
3291 | 3303 | ||
3292 | /* | ||
3293 | * Pass both paths to the journal. The majority of inserts | ||
3294 | * will be touching all components anyway. | ||
3295 | */ | ||
3296 | ret = ocfs2_journal_access_path(inode, handle, right_path); | ||
3297 | if (ret < 0) { | ||
3298 | mlog_errno(ret); | ||
3299 | goto out; | ||
3300 | } | ||
3301 | |||
3302 | if (left_path) { | 3304 | if (left_path) { |
3303 | int credits = handle->h_buffer_credits; | 3305 | int credits = handle->h_buffer_credits; |
3304 | 3306 | ||
@@ -3323,6 +3325,16 @@ static int ocfs2_insert_path(struct inode *inode, | |||
3323 | } | 3325 | } |
3324 | } | 3326 | } |
3325 | 3327 | ||
3328 | /* | ||
3329 | * Pass both paths to the journal. The majority of inserts | ||
3330 | * will be touching all components anyway. | ||
3331 | */ | ||
3332 | ret = ocfs2_journal_access_path(inode, handle, right_path); | ||
3333 | if (ret < 0) { | ||
3334 | mlog_errno(ret); | ||
3335 | goto out; | ||
3336 | } | ||
3337 | |||
3326 | if (insert->ins_split != SPLIT_NONE) { | 3338 | if (insert->ins_split != SPLIT_NONE) { |
3327 | /* | 3339 | /* |
3328 | * We could call ocfs2_insert_at_leaf() for some types | 3340 | * We could call ocfs2_insert_at_leaf() for some types |
@@ -3331,6 +3343,17 @@ static int ocfs2_insert_path(struct inode *inode, | |||
3331 | */ | 3343 | */ |
3332 | ocfs2_split_record(inode, left_path, right_path, | 3344 | ocfs2_split_record(inode, left_path, right_path, |
3333 | insert_rec, insert->ins_split); | 3345 | insert_rec, insert->ins_split); |
3346 | |||
3347 | /* | ||
3348 | * Split might have modified either leaf and we don't | ||
3349 | * have a guarantee that the later edge insert will | ||
3350 | * dirty this for us. | ||
3351 | */ | ||
3352 | if (left_path) | ||
3353 | ret = ocfs2_journal_dirty(handle, | ||
3354 | path_leaf_bh(left_path)); | ||
3355 | if (ret) | ||
3356 | mlog_errno(ret); | ||
3334 | } else | 3357 | } else |
3335 | ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path), | 3358 | ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path), |
3336 | insert, inode); | 3359 | insert, inode); |
@@ -3430,6 +3453,17 @@ static int ocfs2_do_insert_extent(struct inode *inode, | |||
3430 | mlog_errno(ret); | 3453 | mlog_errno(ret); |
3431 | goto out; | 3454 | goto out; |
3432 | } | 3455 | } |
3456 | |||
3457 | /* | ||
3458 | * ocfs2_rotate_tree_right() might have extended the | ||
3459 | * transaction without re-journaling our tree root. | ||
3460 | */ | ||
3461 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
3462 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
3463 | if (ret) { | ||
3464 | mlog_errno(ret); | ||
3465 | goto out; | ||
3466 | } | ||
3433 | } else if (type->ins_appending == APPEND_TAIL | 3467 | } else if (type->ins_appending == APPEND_TAIL |
3434 | && type->ins_contig != CONTIG_LEFT) { | 3468 | && type->ins_contig != CONTIG_LEFT) { |
3435 | ret = ocfs2_append_rec_to_path(inode, handle, insert_rec, | 3469 | ret = ocfs2_append_rec_to_path(inode, handle, insert_rec, |
@@ -3941,7 +3975,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
3941 | { | 3975 | { |
3942 | int ret = 0; | 3976 | int ret = 0; |
3943 | struct ocfs2_extent_list *el = path_leaf_el(path); | 3977 | struct ocfs2_extent_list *el = path_leaf_el(path); |
3944 | struct buffer_head *eb_bh, *last_eb_bh = NULL; | 3978 | struct buffer_head *last_eb_bh = NULL; |
3945 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; | 3979 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; |
3946 | struct ocfs2_merge_ctxt ctxt; | 3980 | struct ocfs2_merge_ctxt ctxt; |
3947 | struct ocfs2_extent_list *rightmost_el; | 3981 | struct ocfs2_extent_list *rightmost_el; |
@@ -3960,14 +3994,6 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
3960 | goto out; | 3994 | goto out; |
3961 | } | 3995 | } |
3962 | 3996 | ||
3963 | eb_bh = path_leaf_bh(path); | ||
3964 | ret = ocfs2_journal_access(handle, inode, eb_bh, | ||
3965 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
3966 | if (ret) { | ||
3967 | mlog_errno(ret); | ||
3968 | goto out; | ||
3969 | } | ||
3970 | |||
3971 | ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el, | 3997 | ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el, |
3972 | split_index, | 3998 | split_index, |
3973 | split_rec); | 3999 | split_rec); |
@@ -4029,8 +4055,6 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4029 | mlog_errno(ret); | 4055 | mlog_errno(ret); |
4030 | } | 4056 | } |
4031 | 4057 | ||
4032 | ocfs2_journal_dirty(handle, eb_bh); | ||
4033 | |||
4034 | out: | 4058 | out: |
4035 | brelse(last_eb_bh); | 4059 | brelse(last_eb_bh); |
4036 | return ret; | 4060 | return ret; |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 0e1250c2ef44..8d81f6c1b877 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -174,6 +174,12 @@ int ocfs2_commit_trans(struct ocfs2_super *osb, | |||
174 | * transaction. extend_trans will either extend the current handle by | 174 | * transaction. extend_trans will either extend the current handle by |
175 | * nblocks, or commit it and start a new one with nblocks credits. | 175 | * nblocks, or commit it and start a new one with nblocks credits. |
176 | * | 176 | * |
177 | * This might call journal_restart() which will commit dirty buffers | ||
178 | * and then restart the transaction. Before calling | ||
179 | * ocfs2_extend_trans(), any changed blocks should have been | ||
180 | * dirtied. After calling it, all blocks which need to be changed must | ||
181 | * go through another set of journal_access/journal_dirty calls. | ||
182 | * | ||
177 | * WARNING: This will not release any semaphores or disk locks taken | 183 | * WARNING: This will not release any semaphores or disk locks taken |
178 | * during the transaction, so make sure they were taken *before* | 184 | * during the transaction, so make sure they were taken *before* |
179 | * start_trans or we'll have ordering deadlocks. | 185 | * start_trans or we'll have ordering deadlocks. |