diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2012-02-20 17:53:02 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-02-20 17:53:02 -0500 |
commit | 0c2022eccb01630c037f2024531e9ff1afbe1564 (patch) | |
tree | 704d54db298e64a84fd60330fd7985d27117d98c /fs/jbd2/transaction.c | |
parent | 18aadd47f88464928b5ce57791c2e8f9f2aaece0 (diff) |
jbd2: allocate transaction from separate slab cache
There is normally only a handful of these active at any one time, but
putting them in a separate slab cache makes debugging memory
corruption problems easier. Manish Katiyar also wanted this make it
easier to test memory failure scenarios in the jbd2 layer.
Cc: Manish Katiyar <mkatiyar@gmail.com>
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2/transaction.c')
-rw-r--r-- | fs/jbd2/transaction.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 526533062548..d0a8b017b281 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -33,6 +33,35 @@ | |||
33 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); | 33 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); |
34 | static void __jbd2_journal_unfile_buffer(struct journal_head *jh); | 34 | static void __jbd2_journal_unfile_buffer(struct journal_head *jh); |
35 | 35 | ||
36 | static struct kmem_cache *transaction_cache; | ||
37 | int __init jbd2_journal_init_transaction_cache(void) | ||
38 | { | ||
39 | J_ASSERT(!transaction_cache); | ||
40 | transaction_cache = kmem_cache_create("jbd2_transaction_s", | ||
41 | sizeof(transaction_t), | ||
42 | 0, | ||
43 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | ||
44 | NULL); | ||
45 | if (transaction_cache) | ||
46 | return 0; | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | |||
50 | void jbd2_journal_destroy_transaction_cache(void) | ||
51 | { | ||
52 | if (transaction_cache) { | ||
53 | kmem_cache_destroy(transaction_cache); | ||
54 | transaction_cache = NULL; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void jbd2_journal_free_transaction(transaction_t *transaction) | ||
59 | { | ||
60 | if (unlikely(ZERO_OR_NULL_PTR(transaction))) | ||
61 | return; | ||
62 | kmem_cache_free(transaction_cache, transaction); | ||
63 | } | ||
64 | |||
36 | /* | 65 | /* |
37 | * jbd2_get_transaction: obtain a new transaction_t object. | 66 | * jbd2_get_transaction: obtain a new transaction_t object. |
38 | * | 67 | * |
@@ -133,7 +162,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle, | |||
133 | 162 | ||
134 | alloc_transaction: | 163 | alloc_transaction: |
135 | if (!journal->j_running_transaction) { | 164 | if (!journal->j_running_transaction) { |
136 | new_transaction = kzalloc(sizeof(*new_transaction), gfp_mask); | 165 | new_transaction = kmem_cache_alloc(transaction_cache, |
166 | gfp_mask | __GFP_ZERO); | ||
137 | if (!new_transaction) { | 167 | if (!new_transaction) { |
138 | /* | 168 | /* |
139 | * If __GFP_FS is not present, then we may be | 169 | * If __GFP_FS is not present, then we may be |
@@ -162,7 +192,7 @@ repeat: | |||
162 | if (is_journal_aborted(journal) || | 192 | if (is_journal_aborted(journal) || |
163 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { | 193 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { |
164 | read_unlock(&journal->j_state_lock); | 194 | read_unlock(&journal->j_state_lock); |
165 | kfree(new_transaction); | 195 | jbd2_journal_free_transaction(new_transaction); |
166 | return -EROFS; | 196 | return -EROFS; |
167 | } | 197 | } |
168 | 198 | ||
@@ -284,7 +314,7 @@ repeat: | |||
284 | read_unlock(&journal->j_state_lock); | 314 | read_unlock(&journal->j_state_lock); |
285 | 315 | ||
286 | lock_map_acquire(&handle->h_lockdep_map); | 316 | lock_map_acquire(&handle->h_lockdep_map); |
287 | kfree(new_transaction); | 317 | jbd2_journal_free_transaction(new_transaction); |
288 | return 0; | 318 | return 0; |
289 | } | 319 | } |
290 | 320 | ||