diff options
Diffstat (limited to 'fs/jbd2/revoke.c')
-rw-r--r-- | fs/jbd2/revoke.c | 165 |
1 files changed, 74 insertions, 91 deletions
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 2e1453a5e998..257ff2625765 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -139,7 +139,7 @@ repeat: | |||
139 | oom: | 139 | oom: |
140 | if (!journal_oom_retry) | 140 | if (!journal_oom_retry) |
141 | return -ENOMEM; | 141 | return -ENOMEM; |
142 | jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__); | 142 | jbd_debug(1, "ENOMEM in %s, retrying\n", __func__); |
143 | yield(); | 143 | yield(); |
144 | goto repeat; | 144 | goto repeat; |
145 | } | 145 | } |
@@ -167,138 +167,121 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, | |||
167 | return NULL; | 167 | return NULL; |
168 | } | 168 | } |
169 | 169 | ||
170 | void jbd2_journal_destroy_revoke_caches(void) | ||
171 | { | ||
172 | if (jbd2_revoke_record_cache) { | ||
173 | kmem_cache_destroy(jbd2_revoke_record_cache); | ||
174 | jbd2_revoke_record_cache = NULL; | ||
175 | } | ||
176 | if (jbd2_revoke_table_cache) { | ||
177 | kmem_cache_destroy(jbd2_revoke_table_cache); | ||
178 | jbd2_revoke_table_cache = NULL; | ||
179 | } | ||
180 | } | ||
181 | |||
170 | int __init jbd2_journal_init_revoke_caches(void) | 182 | int __init jbd2_journal_init_revoke_caches(void) |
171 | { | 183 | { |
184 | J_ASSERT(!jbd2_revoke_record_cache); | ||
185 | J_ASSERT(!jbd2_revoke_table_cache); | ||
186 | |||
172 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", | 187 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", |
173 | sizeof(struct jbd2_revoke_record_s), | 188 | sizeof(struct jbd2_revoke_record_s), |
174 | 0, | 189 | 0, |
175 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 190 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
176 | NULL); | 191 | NULL); |
177 | if (!jbd2_revoke_record_cache) | 192 | if (!jbd2_revoke_record_cache) |
178 | return -ENOMEM; | 193 | goto record_cache_failure; |
179 | 194 | ||
180 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", | 195 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", |
181 | sizeof(struct jbd2_revoke_table_s), | 196 | sizeof(struct jbd2_revoke_table_s), |
182 | 0, SLAB_TEMPORARY, NULL); | 197 | 0, SLAB_TEMPORARY, NULL); |
183 | if (!jbd2_revoke_table_cache) { | 198 | if (!jbd2_revoke_table_cache) |
184 | kmem_cache_destroy(jbd2_revoke_record_cache); | 199 | goto table_cache_failure; |
185 | jbd2_revoke_record_cache = NULL; | ||
186 | return -ENOMEM; | ||
187 | } | ||
188 | return 0; | 200 | return 0; |
201 | table_cache_failure: | ||
202 | jbd2_journal_destroy_revoke_caches(); | ||
203 | record_cache_failure: | ||
204 | return -ENOMEM; | ||
189 | } | 205 | } |
190 | 206 | ||
191 | void jbd2_journal_destroy_revoke_caches(void) | 207 | static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) |
192 | { | 208 | { |
193 | kmem_cache_destroy(jbd2_revoke_record_cache); | 209 | int shift = 0; |
194 | jbd2_revoke_record_cache = NULL; | 210 | int tmp = hash_size; |
195 | kmem_cache_destroy(jbd2_revoke_table_cache); | 211 | struct jbd2_revoke_table_s *table; |
196 | jbd2_revoke_table_cache = NULL; | ||
197 | } | ||
198 | |||
199 | /* Initialise the revoke table for a given journal to a given size. */ | ||
200 | |||
201 | int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | ||
202 | { | ||
203 | int shift, tmp; | ||
204 | 212 | ||
205 | 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; | ||
206 | 216 | ||
207 | shift = 0; | ||
208 | tmp = hash_size; | ||
209 | while((tmp >>= 1UL) != 0UL) | 217 | while((tmp >>= 1UL) != 0UL) |
210 | shift++; | 218 | shift++; |
211 | 219 | ||
212 | journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 220 | table->hash_size = hash_size; |
213 | if (!journal->j_revoke_table[0]) | 221 | table->hash_shift = shift; |
214 | return -ENOMEM; | 222 | table->hash_table = |
215 | journal->j_revoke = journal->j_revoke_table[0]; | ||
216 | |||
217 | /* Check that the hash_size is a power of two */ | ||
218 | J_ASSERT(is_power_of_2(hash_size)); | ||
219 | |||
220 | journal->j_revoke->hash_size = hash_size; | ||
221 | |||
222 | journal->j_revoke->hash_shift = shift; | ||
223 | |||
224 | journal->j_revoke->hash_table = | ||
225 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 223 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); |
226 | if (!journal->j_revoke->hash_table) { | 224 | if (!table->hash_table) { |
227 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 225 | kmem_cache_free(jbd2_revoke_table_cache, table); |
228 | journal->j_revoke = NULL; | 226 | table = NULL; |
229 | return -ENOMEM; | 227 | goto out; |
230 | } | 228 | } |
231 | 229 | ||
232 | for (tmp = 0; tmp < hash_size; tmp++) | 230 | for (tmp = 0; tmp < hash_size; tmp++) |
233 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | 231 | INIT_LIST_HEAD(&table->hash_table[tmp]); |
234 | 232 | ||
235 | journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); | 233 | out: |
236 | if (!journal->j_revoke_table[1]) { | 234 | return table; |
237 | kfree(journal->j_revoke_table[0]->hash_table); | 235 | } |
238 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | 236 | |
239 | 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)); | ||
240 | } | 245 | } |
241 | 246 | ||
242 | journal->j_revoke = journal->j_revoke_table[1]; | 247 | kfree(table->hash_table); |
248 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
249 | } | ||
243 | 250 | ||
244 | /* 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); | ||
245 | J_ASSERT(is_power_of_2(hash_size)); | 255 | J_ASSERT(is_power_of_2(hash_size)); |
246 | 256 | ||
247 | journal->j_revoke->hash_size = hash_size; | 257 | journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size); |
248 | 258 | if (!journal->j_revoke_table[0]) | |
249 | journal->j_revoke->hash_shift = shift; | 259 | goto fail0; |
250 | 260 | ||
251 | journal->j_revoke->hash_table = | 261 | journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size); |
252 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 262 | if (!journal->j_revoke_table[1]) |
253 | if (!journal->j_revoke->hash_table) { | 263 | goto fail1; |
254 | kfree(journal->j_revoke_table[0]->hash_table); | ||
255 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]); | ||
256 | kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]); | ||
257 | journal->j_revoke = NULL; | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | 264 | ||
261 | for (tmp = 0; tmp < hash_size; tmp++) | 265 | journal->j_revoke = journal->j_revoke_table[1]; |
262 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | ||
263 | 266 | ||
264 | spin_lock_init(&journal->j_revoke_lock); | 267 | spin_lock_init(&journal->j_revoke_lock); |
265 | 268 | ||
266 | return 0; | 269 | return 0; |
267 | } | ||
268 | 270 | ||
269 | /* 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 | } | ||
270 | 276 | ||
277 | /* Destroy a journal's revoke table. The table must already be empty! */ | ||
271 | void jbd2_journal_destroy_revoke(journal_t *journal) | 278 | void jbd2_journal_destroy_revoke(journal_t *journal) |
272 | { | 279 | { |
273 | struct jbd2_revoke_table_s *table; | ||
274 | struct list_head *hash_list; | ||
275 | int i; | ||
276 | |||
277 | table = journal->j_revoke_table[0]; | ||
278 | if (!table) | ||
279 | return; | ||
280 | |||
281 | for (i=0; i<table->hash_size; i++) { | ||
282 | hash_list = &table->hash_table[i]; | ||
283 | J_ASSERT (list_empty(hash_list)); | ||
284 | } | ||
285 | |||
286 | kfree(table->hash_table); | ||
287 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
288 | journal->j_revoke = NULL; | ||
289 | |||
290 | table = journal->j_revoke_table[1]; | ||
291 | if (!table) | ||
292 | return; | ||
293 | |||
294 | for (i=0; i<table->hash_size; i++) { | ||
295 | hash_list = &table->hash_table[i]; | ||
296 | J_ASSERT (list_empty(hash_list)); | ||
297 | } | ||
298 | |||
299 | kfree(table->hash_table); | ||
300 | kmem_cache_free(jbd2_revoke_table_cache, table); | ||
301 | 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]); | ||
302 | } | 285 | } |
303 | 286 | ||
304 | 287 | ||