diff options
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/revoke.c | 127 |
1 files changed, 51 insertions, 76 deletions
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 72b260896bbd..144a2065f03e 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -204,109 +204,84 @@ record_cache_failure: | |||
204 | return -ENOMEM; | 204 | return -ENOMEM; |
205 | } | 205 | } |
206 | 206 | ||
207 | /* Initialise the revoke table for a given journal to a given size. */ | 207 | static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) |
208 | |||
209 | int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | ||
210 | { | 208 | { |
211 | int shift, tmp; | 209 | int shift = 0; |
210 | int tmp = hash_size; | ||
211 | struct jbd2_revoke_table_s *table; | ||
212 | 212 | ||
213 | J_ASSERT (journal->j_revoke_table[0] == NULL); | 213 | table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); |
214 | if (!table) | ||
215 | goto out; | ||
214 | 216 | ||
215 | shift = 0; | ||
216 | tmp = hash_size; | ||
217 | while((tmp >>= 1UL) != 0UL) | 217 | while((tmp >>= 1UL) != 0UL) |
218 | shift++; | 218 | shift++; |
219 | 219 | ||
220 | journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 220 | table->hash_size = hash_size; |
221 | if (!journal->j_revoke_table[0]) | 221 | table->hash_shift = shift; |
222 | return -ENOMEM; | 222 | table->hash_table = |
223 | journal->j_revoke = journal->j_revoke_table[0]; | ||
224 | |||
225 | /* Check that the hash_size is a power of two */ | ||
226 | J_ASSERT(is_power_of_2(hash_size)); | ||
227 | |||
228 | journal->j_revoke->hash_size = hash_size; | ||
229 | |||
230 | journal->j_revoke->hash_shift = shift; | ||
231 | |||
232 | journal->j_revoke->hash_table = | ||
233 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 223 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); |
234 | if (!journal->j_revoke->hash_table) { | 224 | if (!table->hash_table) { |
235 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 225 | kmem_cache_free(jbd2_revoke_table_cache, table); |
236 | journal->j_revoke = NULL; | 226 | table = NULL; |
237 | return -ENOMEM; | 227 | goto out; |
238 | } | 228 | } |
239 | 229 | ||
240 | for (tmp = 0; tmp < hash_size; tmp++) | 230 | for (tmp = 0; tmp < hash_size; tmp++) |
241 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | 231 | INIT_LIST_HEAD(&table->hash_table[tmp]); |
242 | 232 | ||
243 | journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 233 | out: |
244 | if (!journal->j_revoke_table[1]) { | 234 | return table; |
245 | kfree(journal->j_revoke_table[0]->hash_table); | 235 | } |
246 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 236 | |
247 | return -ENOMEM; | 237 | static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) |
238 | { | ||
239 | int i; | ||
240 | struct list_head *hash_list; | ||
241 | |||
242 | for (i = 0; i < table->hash_size; i++) { | ||
243 | hash_list = &table->hash_table[i]; | ||
244 | J_ASSERT(list_empty(hash_list)); | ||
248 | } | 245 | } |
249 | 246 | ||
250 | journal->j_revoke = journal->j_revoke_table[1]; | 247 | kfree(table->hash_table); |
248 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
249 | } | ||
251 | 250 | ||
252 | /* Check that the hash_size is a power of two */ | 251 | /* Initialise the revoke table for a given journal to a given size. */ |
252 | int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | ||
253 | { | ||
254 | J_ASSERT(journal->j_revoke_table[0] == NULL); | ||
253 | J_ASSERT(is_power_of_2(hash_size)); | 255 | J_ASSERT(is_power_of_2(hash_size)); |
254 | 256 | ||
255 | journal->j_revoke->hash_size = hash_size; | 257 | journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size); |
258 | if (!journal->j_revoke_table[0]) | ||
259 | goto fail0; | ||
256 | 260 | ||
257 | journal->j_revoke->hash_shift = shift; | 261 | journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size); |
262 | if (!journal->j_revoke_table[1]) | ||
263 | goto fail1; | ||
258 | 264 | ||
259 | journal->j_revoke->hash_table = | 265 | journal->j_revoke = journal->j_revoke_table[1]; |
260 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | ||
261 | if (!journal->j_revoke->hash_table) { | ||
262 | kfree(journal->j_revoke_table[0]->hash_table); | ||
263 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | ||
264 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]); | ||
265 | journal->j_revoke = NULL; | ||
266 | return -ENOMEM; | ||
267 | } | ||
268 | |||
269 | for (tmp = 0; tmp < hash_size; tmp++) | ||
270 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | ||
271 | 266 | ||
272 | spin_lock_init(&journal->j_revoke_lock); | 267 | spin_lock_init(&journal->j_revoke_lock); |
273 | 268 | ||
274 | return 0; | 269 | return 0; |
275 | } | ||
276 | 270 | ||
277 | /* Destoy a journal's revoke table. The table must already be empty! */ | 271 | fail1: |
272 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
273 | fail0: | ||
274 | return -ENOMEM; | ||
275 | } | ||
278 | 276 | ||
277 | /* Destroy a journal's revoke table. The table must already be empty! */ | ||
279 | void jbd2_journal_destroy_revoke(journal_t *journal) | 278 | void jbd2_journal_destroy_revoke(journal_t *journal) |
280 | { | 279 | { |
281 | struct jbd2_revoke_table_s *table; | ||
282 | struct list_head *hash_list; | ||
283 | int i; | ||
284 | |||
285 | table = journal->j_revoke_table[0]; | ||
286 | if (!table) | ||
287 | return; | ||
288 | |||
289 | for (i=0; i<table->hash_size; i++) { | ||
290 | hash_list = &table->hash_table[i]; | ||
291 | J_ASSERT (list_empty(hash_list)); | ||
292 | } | ||
293 | |||
294 | kfree(table->hash_table); | ||
295 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
296 | journal->j_revoke = NULL; | ||
297 | |||
298 | table = journal->j_revoke_table[1]; | ||
299 | if (!table) | ||
300 | return; | ||
301 | |||
302 | for (i=0; i<table->hash_size; i++) { | ||
303 | hash_list = &table->hash_table[i]; | ||
304 | J_ASSERT (list_empty(hash_list)); | ||
305 | } | ||
306 | |||
307 | kfree(table->hash_table); | ||
308 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
309 | journal->j_revoke = NULL; | 280 | journal->j_revoke = NULL; |
281 | if (journal->j_revoke_table[0]) | ||
282 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
283 | if (journal->j_revoke_table[1]) | ||
284 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]); | ||
310 | } | 285 | } |
311 | 286 | ||
312 | 287 | ||