diff options
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 6 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 8 | ||||
-rw-r--r-- | fs/ext4/super.c | 7 |
3 files changed, 14 insertions, 7 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 4c216b1bf20c..aeed0bac693b 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -194,16 +194,20 @@ static inline void ext4_journal_callback_add(handle_t *handle, | |||
194 | * ext4_journal_callback_del: delete a registered callback | 194 | * ext4_journal_callback_del: delete a registered callback |
195 | * @handle: active journal transaction handle on which callback was registered | 195 | * @handle: active journal transaction handle on which callback was registered |
196 | * @jce: registered journal callback entry to unregister | 196 | * @jce: registered journal callback entry to unregister |
197 | * Return true if object was sucessfully removed | ||
197 | */ | 198 | */ |
198 | static inline void ext4_journal_callback_del(handle_t *handle, | 199 | static inline bool ext4_journal_callback_try_del(handle_t *handle, |
199 | struct ext4_journal_cb_entry *jce) | 200 | struct ext4_journal_cb_entry *jce) |
200 | { | 201 | { |
202 | bool deleted; | ||
201 | struct ext4_sb_info *sbi = | 203 | struct ext4_sb_info *sbi = |
202 | EXT4_SB(handle->h_transaction->t_journal->j_private); | 204 | EXT4_SB(handle->h_transaction->t_journal->j_private); |
203 | 205 | ||
204 | spin_lock(&sbi->s_md_lock); | 206 | spin_lock(&sbi->s_md_lock); |
207 | deleted = !list_empty(&jce->jce_list); | ||
205 | list_del_init(&jce->jce_list); | 208 | list_del_init(&jce->jce_list); |
206 | spin_unlock(&sbi->s_md_lock); | 209 | spin_unlock(&sbi->s_md_lock); |
210 | return deleted; | ||
207 | } | 211 | } |
208 | 212 | ||
209 | int | 213 | int |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 36c82a39d03f..580aada3d1bb 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4423,11 +4423,11 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4423 | node = rb_prev(new_node); | 4423 | node = rb_prev(new_node); |
4424 | if (node) { | 4424 | if (node) { |
4425 | entry = rb_entry(node, struct ext4_free_data, efd_node); | 4425 | entry = rb_entry(node, struct ext4_free_data, efd_node); |
4426 | if (can_merge(entry, new_entry)) { | 4426 | if (can_merge(entry, new_entry) && |
4427 | ext4_journal_callback_try_del(handle, &entry->efd_jce)) { | ||
4427 | new_entry->efd_start_cluster = entry->efd_start_cluster; | 4428 | new_entry->efd_start_cluster = entry->efd_start_cluster; |
4428 | new_entry->efd_count += entry->efd_count; | 4429 | new_entry->efd_count += entry->efd_count; |
4429 | rb_erase(node, &(db->bb_free_root)); | 4430 | rb_erase(node, &(db->bb_free_root)); |
4430 | ext4_journal_callback_del(handle, &entry->efd_jce); | ||
4431 | kmem_cache_free(ext4_free_data_cachep, entry); | 4431 | kmem_cache_free(ext4_free_data_cachep, entry); |
4432 | } | 4432 | } |
4433 | } | 4433 | } |
@@ -4435,10 +4435,10 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4435 | node = rb_next(new_node); | 4435 | node = rb_next(new_node); |
4436 | if (node) { | 4436 | if (node) { |
4437 | entry = rb_entry(node, struct ext4_free_data, efd_node); | 4437 | entry = rb_entry(node, struct ext4_free_data, efd_node); |
4438 | if (can_merge(new_entry, entry)) { | 4438 | if (can_merge(new_entry, entry) && |
4439 | ext4_journal_callback_try_del(handle, &entry->efd_jce)) { | ||
4439 | new_entry->efd_count += entry->efd_count; | 4440 | new_entry->efd_count += entry->efd_count; |
4440 | rb_erase(node, &(db->bb_free_root)); | 4441 | rb_erase(node, &(db->bb_free_root)); |
4441 | ext4_journal_callback_del(handle, &entry->efd_jce); | ||
4442 | kmem_cache_free(ext4_free_data_cachep, entry); | 4442 | kmem_cache_free(ext4_free_data_cachep, entry); |
4443 | } | 4443 | } |
4444 | } | 4444 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 5d6d53578124..67ae9e332d42 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -353,10 +353,13 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) | |||
353 | struct super_block *sb = journal->j_private; | 353 | struct super_block *sb = journal->j_private; |
354 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 354 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
355 | int error = is_journal_aborted(journal); | 355 | int error = is_journal_aborted(journal); |
356 | struct ext4_journal_cb_entry *jce, *tmp; | 356 | struct ext4_journal_cb_entry *jce; |
357 | 357 | ||
358 | BUG_ON(txn->t_state == T_FINISHED); | ||
358 | spin_lock(&sbi->s_md_lock); | 359 | spin_lock(&sbi->s_md_lock); |
359 | list_for_each_entry_safe(jce, tmp, &txn->t_private_list, jce_list) { | 360 | while (!list_empty(&txn->t_private_list)) { |
361 | jce = list_entry(txn->t_private_list.next, | ||
362 | struct ext4_journal_cb_entry, jce_list); | ||
360 | list_del_init(&jce->jce_list); | 363 | list_del_init(&jce->jce_list); |
361 | spin_unlock(&sbi->s_md_lock); | 364 | spin_unlock(&sbi->s_md_lock); |
362 | jce->jce_func(sb, jce, error); | 365 | jce->jce_func(sb, jce, error); |