return status;
}
-static struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb)
-{
- struct ocfs2_journal_handle *retval = NULL;
-
- retval = kcalloc(1, sizeof(*retval), GFP_NOFS);
- if (!retval) {
- mlog(ML_ERROR, "Failed to allocate memory for journal "
- "handle!\n");
- return NULL;
- }
- retval->k_handle = NULL;
-
- return retval;
-}
-
/* pass it NULL and it will allocate a new handle object for you. If
* you pass it a handle however, it may still return error, in which
* case it has free'd the passed handle for you. */
-struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
- int max_buffs)
+handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
{
- int ret;
journal_t *journal = osb->journal->j_journal;
-
- mlog_entry("(max_buffs = %d)\n", max_buffs);
+ handle_t *handle;
BUG_ON(!osb || !osb->journal->j_journal);
- if (ocfs2_is_hard_readonly(osb)) {
- ret = -EROFS;
- goto done_free;
- }
+ if (ocfs2_is_hard_readonly(osb))
+ return ERR_PTR(-EROFS);
BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE);
BUG_ON(max_buffs <= 0);
BUG();
}
- if (!handle)
- handle = ocfs2_alloc_handle(osb);
- if (!handle) {
- ret = -ENOMEM;
- mlog(ML_ERROR, "Failed to allocate memory for journal "
- "handle!\n");
- goto done_free;
- }
-
down_read(&osb->journal->j_trans_barrier);
- /* actually start the transaction now */
- handle->k_handle = journal_start(journal, max_buffs);
- if (IS_ERR(handle->k_handle)) {
+ handle = journal_start(journal, max_buffs);
+ if (IS_ERR(handle)) {
up_read(&osb->journal->j_trans_barrier);
- ret = PTR_ERR(handle->k_handle);
- handle->k_handle = NULL;
- mlog_errno(ret);
+ mlog_errno(PTR_ERR(handle));
if (is_journal_aborted(journal)) {
ocfs2_abort(osb->sb, "Detected aborted journal");
- ret = -EROFS;
+ handle = ERR_PTR(-EROFS);
}
- goto done_free;
+ } else {
+ if (!ocfs2_mount_local(osb))
+ atomic_inc(&(osb->journal->j_num_trans));
}
- atomic_inc(&(osb->journal->j_num_trans));
-
- mlog_exit_ptr(handle);
return handle;
-
-done_free:
- if (handle)
- kfree(handle);
-
- mlog_exit(ret);
- return ERR_PTR(ret);
}
-void ocfs2_commit_trans(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle)
+int ocfs2_commit_trans(struct ocfs2_super *osb,
+ handle_t *handle)
{
- handle_t *jbd_handle;
- int retval;
+ int ret;
struct ocfs2_journal *journal = osb->journal;
- mlog_entry_void();
-
BUG_ON(!handle);
- if (!handle->k_handle) {
- kfree(handle);
- mlog_exit_void();
- return;
- }
-
- /* ocfs2_extend_trans may have had to call journal_restart
- * which will always commit the transaction, but may return
- * error for any number of reasons. If this is the case, we
- * clear k_handle as it's not valid any more. */
- if (handle->k_handle) {
- jbd_handle = handle->k_handle;
-
- /* actually stop the transaction. if we've set h_sync,
- * it'll have been committed when we return */
- retval = journal_stop(jbd_handle);
- if (retval < 0) {
- mlog_errno(retval);
- mlog(ML_ERROR, "Could not commit transaction\n");
- BUG();
- }
-
- handle->k_handle = NULL; /* it's been free'd in journal_stop */
- }
+ ret = journal_stop(handle);
+ if (ret < 0)
+ mlog_errno(ret);
up_read(&journal->j_trans_barrier);
- kfree(handle);
- mlog_exit_void();
+ return ret;
}
/*
return status;
}
-int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
+int ocfs2_journal_access(handle_t *handle,
struct inode *inode,
struct buffer_head *bh,
int type)
switch (type) {
case OCFS2_JOURNAL_ACCESS_CREATE:
case OCFS2_JOURNAL_ACCESS_WRITE:
- status = journal_get_write_access(handle->k_handle, bh);
+ status = journal_get_write_access(handle, bh);
break;
case OCFS2_JOURNAL_ACCESS_UNDO:
- status = journal_get_undo_access(handle->k_handle, bh);
+ status = journal_get_undo_access(handle, bh);
break;
default:
return status;
}
-int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle,
+int ocfs2_journal_dirty(handle_t *handle,
struct buffer_head *bh)
{
int status;
mlog_entry("(bh->b_blocknr=%llu)\n",
(unsigned long long)bh->b_blocknr);
- status = journal_dirty_metadata(handle->k_handle, bh);
+ status = journal_dirty_metadata(handle, bh);
if (status < 0)
mlog(ML_ERROR, "Could not dirty metadata buffer. "
"(bh->b_blocknr=%llu)\n",
BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
- status = ocfs2_journal_toggle_dirty(osb, 0);
- if (status < 0)
- mlog_errno(status);
+ if (ocfs2_mount_local(osb)) {
+ journal_lock_updates(journal->j_journal);
+ status = journal_flush(journal->j_journal);
+ journal_unlock_updates(journal->j_journal);
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+ if (status == 0) {
+ /*
+ * Do not toggle if flush was unsuccessful otherwise
+ * will leave dirty metadata in a "clean" journal
+ */
+ status = ocfs2_journal_toggle_dirty(osb, 0);
+ if (status < 0)
+ mlog_errno(status);
+ }
/* Shutdown the kernel journal system */
journal_destroy(journal->j_journal);
}
}
-int ocfs2_journal_load(struct ocfs2_journal *journal)
+int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
{
int status = 0;
struct ocfs2_super *osb;
}
/* Launch the commit thread */
- osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt");
- if (IS_ERR(osb->commit_task)) {
- status = PTR_ERR(osb->commit_task);
+ if (!local) {
+ osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
+ "ocfs2cmt");
+ if (IS_ERR(osb->commit_task)) {
+ status = PTR_ERR(osb->commit_task);
+ osb->commit_task = NULL;
+ mlog(ML_ERROR, "unable to launch ocfs2commit thread, "
+ "error=%d", status);
+ goto done;
+ }
+ } else
osb->commit_task = NULL;
- mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
- status);
- goto done;
- }
done:
mlog_exit(status);
* NOTE: This function can and will sleep on recovery of other nodes
* during cluster locking, just like any other ocfs2 process.
*/
-void ocfs2_complete_recovery(void *data)
+void ocfs2_complete_recovery(struct work_struct *work)
{
int ret;
- struct ocfs2_super *osb = data;
- struct ocfs2_journal *journal = osb->journal;
+ struct ocfs2_journal *journal =
+ container_of(work, struct ocfs2_journal, j_recovery_work);
+ struct ocfs2_super *osb = journal->j_osb;
struct ocfs2_dinode *la_dinode, *tl_dinode;
struct ocfs2_la_recovery_item *item;
struct list_head *p, *n;
continue;
iter = ocfs2_iget(osb, le64_to_cpu(de->inode),
- OCFS2_FI_FLAG_NOLOCK);
+ OCFS2_FI_FLAG_ORPHAN_RECOVERY);
if (IS_ERR(iter))
continue;
/* Set the proper information to get us going into
* ocfs2_delete_inode. */
oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
- oi->ip_orphaned_slot = slot;
spin_unlock(&oi->ip_lock);
iput(inode);