diff options
Diffstat (limited to 'fs/ocfs2/journal.c')
-rw-r--r-- | fs/ocfs2/journal.c | 271 |
1 files changed, 31 insertions, 240 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index d95ee2720e6e..1d7f4ab1e5ed 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -57,9 +57,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, | |||
57 | static int __ocfs2_recovery_thread(void *arg); | 57 | static int __ocfs2_recovery_thread(void *arg); |
58 | static int ocfs2_commit_cache(struct ocfs2_super *osb); | 58 | static int ocfs2_commit_cache(struct ocfs2_super *osb); |
59 | static int ocfs2_wait_on_mount(struct ocfs2_super *osb); | 59 | static int ocfs2_wait_on_mount(struct ocfs2_super *osb); |
60 | static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal, | ||
61 | struct ocfs2_journal_handle *handle); | ||
62 | static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle); | ||
63 | static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, | 60 | static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, |
64 | int dirty); | 61 | int dirty); |
65 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, | 62 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, |
@@ -113,46 +110,18 @@ finally: | |||
113 | return status; | 110 | return status; |
114 | } | 111 | } |
115 | 112 | ||
116 | struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) | ||
117 | { | ||
118 | struct ocfs2_journal_handle *retval = NULL; | ||
119 | |||
120 | retval = kcalloc(1, sizeof(*retval), GFP_NOFS); | ||
121 | if (!retval) { | ||
122 | mlog(ML_ERROR, "Failed to allocate memory for journal " | ||
123 | "handle!\n"); | ||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | retval->max_buffs = 0; | ||
128 | retval->num_locks = 0; | ||
129 | retval->k_handle = NULL; | ||
130 | |||
131 | INIT_LIST_HEAD(&retval->locks); | ||
132 | INIT_LIST_HEAD(&retval->inode_list); | ||
133 | retval->journal = osb->journal; | ||
134 | |||
135 | return retval; | ||
136 | } | ||
137 | |||
138 | /* pass it NULL and it will allocate a new handle object for you. If | 113 | /* pass it NULL and it will allocate a new handle object for you. If |
139 | * you pass it a handle however, it may still return error, in which | 114 | * you pass it a handle however, it may still return error, in which |
140 | * case it has free'd the passed handle for you. */ | 115 | * case it has free'd the passed handle for you. */ |
141 | struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, | 116 | handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs) |
142 | struct ocfs2_journal_handle *handle, | ||
143 | int max_buffs) | ||
144 | { | 117 | { |
145 | int ret; | ||
146 | journal_t *journal = osb->journal->j_journal; | 118 | journal_t *journal = osb->journal->j_journal; |
147 | 119 | handle_t *handle; | |
148 | mlog_entry("(max_buffs = %d)\n", max_buffs); | ||
149 | 120 | ||
150 | BUG_ON(!osb || !osb->journal->j_journal); | 121 | BUG_ON(!osb || !osb->journal->j_journal); |
151 | 122 | ||
152 | if (ocfs2_is_hard_readonly(osb)) { | 123 | if (ocfs2_is_hard_readonly(osb)) |
153 | ret = -EROFS; | 124 | return ERR_PTR(-EROFS); |
154 | goto done_free; | ||
155 | } | ||
156 | 125 | ||
157 | BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE); | 126 | BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE); |
158 | BUG_ON(max_buffs <= 0); | 127 | BUG_ON(max_buffs <= 0); |
@@ -163,154 +132,39 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, | |||
163 | BUG(); | 132 | BUG(); |
164 | } | 133 | } |
165 | 134 | ||
166 | if (!handle) | ||
167 | handle = ocfs2_alloc_handle(osb); | ||
168 | if (!handle) { | ||
169 | ret = -ENOMEM; | ||
170 | mlog(ML_ERROR, "Failed to allocate memory for journal " | ||
171 | "handle!\n"); | ||
172 | goto done_free; | ||
173 | } | ||
174 | |||
175 | handle->max_buffs = max_buffs; | ||
176 | |||
177 | down_read(&osb->journal->j_trans_barrier); | 135 | down_read(&osb->journal->j_trans_barrier); |
178 | 136 | ||
179 | /* actually start the transaction now */ | 137 | handle = journal_start(journal, max_buffs); |
180 | handle->k_handle = journal_start(journal, max_buffs); | 138 | if (IS_ERR(handle)) { |
181 | if (IS_ERR(handle->k_handle)) { | ||
182 | up_read(&osb->journal->j_trans_barrier); | 139 | up_read(&osb->journal->j_trans_barrier); |
183 | 140 | ||
184 | ret = PTR_ERR(handle->k_handle); | 141 | mlog_errno(PTR_ERR(handle)); |
185 | handle->k_handle = NULL; | ||
186 | mlog_errno(ret); | ||
187 | 142 | ||
188 | if (is_journal_aborted(journal)) { | 143 | if (is_journal_aborted(journal)) { |
189 | ocfs2_abort(osb->sb, "Detected aborted journal"); | 144 | ocfs2_abort(osb->sb, "Detected aborted journal"); |
190 | ret = -EROFS; | 145 | handle = ERR_PTR(-EROFS); |
191 | } | 146 | } |
192 | goto done_free; | 147 | } else |
193 | } | 148 | atomic_inc(&(osb->journal->j_num_trans)); |
194 | |||
195 | atomic_inc(&(osb->journal->j_num_trans)); | ||
196 | handle->flags |= OCFS2_HANDLE_STARTED; | ||
197 | 149 | ||
198 | mlog_exit_ptr(handle); | ||
199 | return handle; | 150 | return handle; |
200 | |||
201 | done_free: | ||
202 | if (handle) | ||
203 | ocfs2_commit_unstarted_handle(handle); /* will kfree handle */ | ||
204 | |||
205 | mlog_exit(ret); | ||
206 | return ERR_PTR(ret); | ||
207 | } | ||
208 | |||
209 | void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle, | ||
210 | struct inode *inode) | ||
211 | { | ||
212 | BUG_ON(!handle); | ||
213 | BUG_ON(!inode); | ||
214 | |||
215 | atomic_inc(&inode->i_count); | ||
216 | |||
217 | /* we're obviously changing it... */ | ||
218 | mutex_lock(&inode->i_mutex); | ||
219 | |||
220 | /* sanity check */ | ||
221 | BUG_ON(OCFS2_I(inode)->ip_handle); | ||
222 | BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list)); | ||
223 | |||
224 | OCFS2_I(inode)->ip_handle = handle; | ||
225 | list_move_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list)); | ||
226 | } | ||
227 | |||
228 | static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle) | ||
229 | { | ||
230 | struct list_head *p, *n; | ||
231 | struct inode *inode; | ||
232 | struct ocfs2_inode_info *oi; | ||
233 | |||
234 | list_for_each_safe(p, n, &handle->inode_list) { | ||
235 | oi = list_entry(p, struct ocfs2_inode_info, | ||
236 | ip_handle_list); | ||
237 | inode = &oi->vfs_inode; | ||
238 | |||
239 | OCFS2_I(inode)->ip_handle = NULL; | ||
240 | list_del_init(&OCFS2_I(inode)->ip_handle_list); | ||
241 | |||
242 | mutex_unlock(&inode->i_mutex); | ||
243 | iput(inode); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* This is trivial so we do it out of the main commit | ||
248 | * paths. Beware, it can be called from start_trans too! */ | ||
249 | static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle) | ||
250 | { | ||
251 | mlog_entry_void(); | ||
252 | |||
253 | BUG_ON(handle->flags & OCFS2_HANDLE_STARTED); | ||
254 | |||
255 | ocfs2_handle_unlock_inodes(handle); | ||
256 | /* You are allowed to add journal locks before the transaction | ||
257 | * has started. */ | ||
258 | ocfs2_handle_cleanup_locks(handle->journal, handle); | ||
259 | |||
260 | kfree(handle); | ||
261 | |||
262 | mlog_exit_void(); | ||
263 | } | 151 | } |
264 | 152 | ||
265 | void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) | 153 | int ocfs2_commit_trans(struct ocfs2_super *osb, |
154 | handle_t *handle) | ||
266 | { | 155 | { |
267 | handle_t *jbd_handle; | 156 | int ret; |
268 | int retval; | 157 | struct ocfs2_journal *journal = osb->journal; |
269 | struct ocfs2_journal *journal = handle->journal; | ||
270 | |||
271 | mlog_entry_void(); | ||
272 | 158 | ||
273 | BUG_ON(!handle); | 159 | BUG_ON(!handle); |
274 | 160 | ||
275 | if (!(handle->flags & OCFS2_HANDLE_STARTED)) { | 161 | ret = journal_stop(handle); |
276 | ocfs2_commit_unstarted_handle(handle); | 162 | if (ret < 0) |
277 | mlog_exit_void(); | 163 | mlog_errno(ret); |
278 | return; | ||
279 | } | ||
280 | |||
281 | /* release inode semaphores we took during this transaction */ | ||
282 | ocfs2_handle_unlock_inodes(handle); | ||
283 | |||
284 | /* ocfs2_extend_trans may have had to call journal_restart | ||
285 | * which will always commit the transaction, but may return | ||
286 | * error for any number of reasons. If this is the case, we | ||
287 | * clear k_handle as it's not valid any more. */ | ||
288 | if (handle->k_handle) { | ||
289 | jbd_handle = handle->k_handle; | ||
290 | |||
291 | if (handle->flags & OCFS2_HANDLE_SYNC) | ||
292 | jbd_handle->h_sync = 1; | ||
293 | else | ||
294 | jbd_handle->h_sync = 0; | ||
295 | |||
296 | /* actually stop the transaction. if we've set h_sync, | ||
297 | * it'll have been committed when we return */ | ||
298 | retval = journal_stop(jbd_handle); | ||
299 | if (retval < 0) { | ||
300 | mlog_errno(retval); | ||
301 | mlog(ML_ERROR, "Could not commit transaction\n"); | ||
302 | BUG(); | ||
303 | } | ||
304 | |||
305 | handle->k_handle = NULL; /* it's been free'd in journal_stop */ | ||
306 | } | ||
307 | |||
308 | ocfs2_handle_cleanup_locks(journal, handle); | ||
309 | 164 | ||
310 | up_read(&journal->j_trans_barrier); | 165 | up_read(&journal->j_trans_barrier); |
311 | 166 | ||
312 | kfree(handle); | 167 | return ret; |
313 | mlog_exit_void(); | ||
314 | } | 168 | } |
315 | 169 | ||
316 | /* | 170 | /* |
@@ -326,20 +180,18 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle) | |||
326 | * good because transaction ids haven't yet been recorded on the | 180 | * good because transaction ids haven't yet been recorded on the |
327 | * cluster locks associated with this handle. | 181 | * cluster locks associated with this handle. |
328 | */ | 182 | */ |
329 | int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, | 183 | int ocfs2_extend_trans(handle_t *handle, int nblocks) |
330 | int nblocks) | ||
331 | { | 184 | { |
332 | int status; | 185 | int status; |
333 | 186 | ||
334 | BUG_ON(!handle); | 187 | BUG_ON(!handle); |
335 | BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); | ||
336 | BUG_ON(!nblocks); | 188 | BUG_ON(!nblocks); |
337 | 189 | ||
338 | mlog_entry_void(); | 190 | mlog_entry_void(); |
339 | 191 | ||
340 | mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); | 192 | mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); |
341 | 193 | ||
342 | status = journal_extend(handle->k_handle, nblocks); | 194 | status = journal_extend(handle, nblocks); |
343 | if (status < 0) { | 195 | if (status < 0) { |
344 | mlog_errno(status); | 196 | mlog_errno(status); |
345 | goto bail; | 197 | goto bail; |
@@ -347,15 +199,12 @@ int ocfs2_extend_trans(struct ocfs2_journal_handle *handle, | |||
347 | 199 | ||
348 | if (status > 0) { | 200 | if (status > 0) { |
349 | mlog(0, "journal_extend failed, trying journal_restart\n"); | 201 | mlog(0, "journal_extend failed, trying journal_restart\n"); |
350 | status = journal_restart(handle->k_handle, nblocks); | 202 | status = journal_restart(handle, nblocks); |
351 | if (status < 0) { | 203 | if (status < 0) { |
352 | handle->k_handle = NULL; | ||
353 | mlog_errno(status); | 204 | mlog_errno(status); |
354 | goto bail; | 205 | goto bail; |
355 | } | 206 | } |
356 | handle->max_buffs = nblocks; | 207 | } |
357 | } else | ||
358 | handle->max_buffs += nblocks; | ||
359 | 208 | ||
360 | status = 0; | 209 | status = 0; |
361 | bail: | 210 | bail: |
@@ -364,7 +213,7 @@ bail: | |||
364 | return status; | 213 | return status; |
365 | } | 214 | } |
366 | 215 | ||
367 | int ocfs2_journal_access(struct ocfs2_journal_handle *handle, | 216 | int ocfs2_journal_access(handle_t *handle, |
368 | struct inode *inode, | 217 | struct inode *inode, |
369 | struct buffer_head *bh, | 218 | struct buffer_head *bh, |
370 | int type) | 219 | int type) |
@@ -374,7 +223,6 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, | |||
374 | BUG_ON(!inode); | 223 | BUG_ON(!inode); |
375 | BUG_ON(!handle); | 224 | BUG_ON(!handle); |
376 | BUG_ON(!bh); | 225 | BUG_ON(!bh); |
377 | BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); | ||
378 | 226 | ||
379 | mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", | 227 | mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", |
380 | (unsigned long long)bh->b_blocknr, type, | 228 | (unsigned long long)bh->b_blocknr, type, |
@@ -403,11 +251,11 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, | |||
403 | switch (type) { | 251 | switch (type) { |
404 | case OCFS2_JOURNAL_ACCESS_CREATE: | 252 | case OCFS2_JOURNAL_ACCESS_CREATE: |
405 | case OCFS2_JOURNAL_ACCESS_WRITE: | 253 | case OCFS2_JOURNAL_ACCESS_WRITE: |
406 | status = journal_get_write_access(handle->k_handle, bh); | 254 | status = journal_get_write_access(handle, bh); |
407 | break; | 255 | break; |
408 | 256 | ||
409 | case OCFS2_JOURNAL_ACCESS_UNDO: | 257 | case OCFS2_JOURNAL_ACCESS_UNDO: |
410 | status = journal_get_undo_access(handle->k_handle, bh); | 258 | status = journal_get_undo_access(handle, bh); |
411 | break; | 259 | break; |
412 | 260 | ||
413 | default: | 261 | default: |
@@ -424,17 +272,15 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, | |||
424 | return status; | 272 | return status; |
425 | } | 273 | } |
426 | 274 | ||
427 | int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle, | 275 | int ocfs2_journal_dirty(handle_t *handle, |
428 | struct buffer_head *bh) | 276 | struct buffer_head *bh) |
429 | { | 277 | { |
430 | int status; | 278 | int status; |
431 | 279 | ||
432 | BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED)); | ||
433 | |||
434 | mlog_entry("(bh->b_blocknr=%llu)\n", | 280 | mlog_entry("(bh->b_blocknr=%llu)\n", |
435 | (unsigned long long)bh->b_blocknr); | 281 | (unsigned long long)bh->b_blocknr); |
436 | 282 | ||
437 | status = journal_dirty_metadata(handle->k_handle, bh); | 283 | status = journal_dirty_metadata(handle, bh); |
438 | if (status < 0) | 284 | if (status < 0) |
439 | mlog(ML_ERROR, "Could not dirty metadata buffer. " | 285 | mlog(ML_ERROR, "Could not dirty metadata buffer. " |
440 | "(bh->b_blocknr=%llu)\n", | 286 | "(bh->b_blocknr=%llu)\n", |
@@ -456,59 +302,6 @@ int ocfs2_journal_dirty_data(handle_t *handle, | |||
456 | return err; | 302 | return err; |
457 | } | 303 | } |
458 | 304 | ||
459 | /* We always assume you're adding a metadata lock at level 'ex' */ | ||
460 | int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle, | ||
461 | struct inode *inode) | ||
462 | { | ||
463 | int status; | ||
464 | struct ocfs2_journal_lock *lock; | ||
465 | |||
466 | BUG_ON(!inode); | ||
467 | |||
468 | lock = kmem_cache_alloc(ocfs2_lock_cache, GFP_NOFS); | ||
469 | if (!lock) { | ||
470 | status = -ENOMEM; | ||
471 | mlog_errno(-ENOMEM); | ||
472 | goto bail; | ||
473 | } | ||
474 | |||
475 | if (!igrab(inode)) | ||
476 | BUG(); | ||
477 | lock->jl_inode = inode; | ||
478 | |||
479 | list_add_tail(&(lock->jl_lock_list), &(handle->locks)); | ||
480 | handle->num_locks++; | ||
481 | |||
482 | status = 0; | ||
483 | bail: | ||
484 | mlog_exit(status); | ||
485 | return status; | ||
486 | } | ||
487 | |||
488 | static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal, | ||
489 | struct ocfs2_journal_handle *handle) | ||
490 | { | ||
491 | struct list_head *p, *n; | ||
492 | struct ocfs2_journal_lock *lock; | ||
493 | struct inode *inode; | ||
494 | |||
495 | list_for_each_safe(p, n, &(handle->locks)) { | ||
496 | lock = list_entry(p, struct ocfs2_journal_lock, | ||
497 | jl_lock_list); | ||
498 | list_del(&lock->jl_lock_list); | ||
499 | handle->num_locks--; | ||
500 | |||
501 | inode = lock->jl_inode; | ||
502 | ocfs2_meta_unlock(inode, 1); | ||
503 | if (atomic_read(&inode->i_count) == 1) | ||
504 | mlog(ML_ERROR, | ||
505 | "Inode %llu, I'm doing a last iput for!", | ||
506 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
507 | iput(inode); | ||
508 | kmem_cache_free(ocfs2_lock_cache, lock); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | #define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * 5) | 305 | #define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * 5) |
513 | 306 | ||
514 | void ocfs2_set_journal_params(struct ocfs2_super *osb) | 307 | void ocfs2_set_journal_params(struct ocfs2_super *osb) |
@@ -562,8 +355,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) | |||
562 | /* Skip recovery waits here - journal inode metadata never | 355 | /* Skip recovery waits here - journal inode metadata never |
563 | * changes in a live cluster so it can be considered an | 356 | * changes in a live cluster so it can be considered an |
564 | * exception to the rule. */ | 357 | * exception to the rule. */ |
565 | status = ocfs2_meta_lock_full(inode, NULL, &bh, 1, | 358 | status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); |
566 | OCFS2_META_LOCK_RECOVERY); | ||
567 | if (status < 0) { | 359 | if (status < 0) { |
568 | if (status != -ERESTARTSYS) | 360 | if (status != -ERESTARTSYS) |
569 | mlog(ML_ERROR, "Could not get lock on journal!\n"); | 361 | mlog(ML_ERROR, "Could not get lock on journal!\n"); |
@@ -1161,8 +953,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, | |||
1161 | } | 953 | } |
1162 | SET_INODE_JOURNAL(inode); | 954 | SET_INODE_JOURNAL(inode); |
1163 | 955 | ||
1164 | status = ocfs2_meta_lock_full(inode, NULL, &bh, 1, | 956 | status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); |
1165 | OCFS2_META_LOCK_RECOVERY); | ||
1166 | if (status < 0) { | 957 | if (status < 0) { |
1167 | mlog(0, "status returned from ocfs2_meta_lock=%d\n", status); | 958 | mlog(0, "status returned from ocfs2_meta_lock=%d\n", status); |
1168 | if (status != -ERESTARTSYS) | 959 | if (status != -ERESTARTSYS) |
@@ -1351,7 +1142,7 @@ static int ocfs2_trylock_journal(struct ocfs2_super *osb, | |||
1351 | SET_INODE_JOURNAL(inode); | 1142 | SET_INODE_JOURNAL(inode); |
1352 | 1143 | ||
1353 | flags = OCFS2_META_LOCK_RECOVERY | OCFS2_META_LOCK_NOQUEUE; | 1144 | flags = OCFS2_META_LOCK_RECOVERY | OCFS2_META_LOCK_NOQUEUE; |
1354 | status = ocfs2_meta_lock_full(inode, NULL, NULL, 1, flags); | 1145 | status = ocfs2_meta_lock_full(inode, NULL, 1, flags); |
1355 | if (status < 0) { | 1146 | if (status < 0) { |
1356 | if (status != -EAGAIN) | 1147 | if (status != -EAGAIN) |
1357 | mlog_errno(status); | 1148 | mlog_errno(status); |
@@ -1434,7 +1225,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, | |||
1434 | } | 1225 | } |
1435 | 1226 | ||
1436 | mutex_lock(&orphan_dir_inode->i_mutex); | 1227 | mutex_lock(&orphan_dir_inode->i_mutex); |
1437 | status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0); | 1228 | status = ocfs2_meta_lock(orphan_dir_inode, NULL, 0); |
1438 | if (status < 0) { | 1229 | if (status < 0) { |
1439 | mlog_errno(status); | 1230 | mlog_errno(status); |
1440 | goto out; | 1231 | goto out; |