/** * void journal_destroy() - Release a journal_t structure. * @journal: Journal to act on. * * Release a journal_t structure once it is no longer in use by the * journaled object. */ void journal_destroy(journal_t *journal) { #if 0 /* Wait for the commit thread to wake up and die. */ journal_kill_thread(journal); /* Force a final log commit */ if (journal->j_running_transaction) journal_commit_transaction(journal); /* Force any old transactions to disk */ /* Totally anal locking here... */ jbd_lock(&journal->j_list_lock); while (journal->j_checkpoint_transactions != NULL) { jbd_unlock(&journal->j_list_lock); log_do_checkpoint(journal); jbd_lock(&journal->j_list_lock); } J_ASSERT(journal->j_running_transaction == NULL); J_ASSERT(journal->j_committing_transaction == NULL); J_ASSERT(journal->j_checkpoint_transactions == NULL); jbd_unlock(&journal->j_list_lock); /* We can now mark the journal as empty. */ journal->j_tail = 0; journal->j_tail_sequence = ++journal->j_transaction_sequence; if (journal->j_sb_buffer) { journal_update_superblock(journal, 1); brelse(journal->j_sb_buffer); } #endif if (journal->j_sb_buffer) { brelse(journal->j_sb_buffer); } if (journal->j_inode) iput(journal->j_inode); if (journal->j_revoke) journal_destroy_revoke(journal); kfree(journal->j_wbuf); kfree(journal); }
static int kjournald(void *arg) { journal_t *journal = arg; transaction_t *transaction; /* * Set up an interval timer which can be used to trigger a commit wakeup * after the commit interval expires */ setup_timer(&journal->j_commit_timer, commit_timeout, (unsigned long)current); set_freezable(); /* Record that the journal thread is running */ journal->j_task = current; wake_up(&journal->j_wait_done_commit); printk(KERN_INFO "kjournald starting. Commit interval %ld seconds\n", journal->j_commit_interval / HZ); /* * And now, wait forever for commit wakeup events. */ spin_lock(&journal->j_state_lock); loop: if (journal->j_flags & JFS_UNMOUNT) goto end_loop; jbd_debug(1, "commit_sequence=%d, commit_request=%d\n", journal->j_commit_sequence, journal->j_commit_request); if (journal->j_commit_sequence != journal->j_commit_request) { jbd_debug(1, "OK, requests differ\n"); spin_unlock(&journal->j_state_lock); del_timer_sync(&journal->j_commit_timer); journal_commit_transaction(journal); spin_lock(&journal->j_state_lock); goto loop; } wake_up(&journal->j_wait_done_commit); if (freezing(current)) { /* * The simpler the better. Flushing journal isn't a * good idea, because that depends on threads that may * be already stopped. */ jbd_debug(1, "Now suspending kjournald\n"); spin_unlock(&journal->j_state_lock); try_to_freeze(); spin_lock(&journal->j_state_lock); } else { /* * We assume on resume that commits are already there, * so we don't sleep */ DEFINE_WAIT(wait); int should_sleep = 1; prepare_to_wait(&journal->j_wait_commit, &wait, TASK_INTERRUPTIBLE); if (journal->j_commit_sequence != journal->j_commit_request) should_sleep = 0; transaction = journal->j_running_transaction; if (transaction && time_after_eq(jiffies, transaction->t_expires)) should_sleep = 0; if (journal->j_flags & JFS_UNMOUNT) should_sleep = 0; if (should_sleep) { spin_unlock(&journal->j_state_lock); schedule(); spin_lock(&journal->j_state_lock); } finish_wait(&journal->j_wait_commit, &wait); } jbd_debug(1, "kjournald wakes\n"); /* * Were we woken up by a commit wakeup event? */ transaction = journal->j_running_transaction; if (transaction && time_after_eq(jiffies, transaction->t_expires)) { journal->j_commit_request = transaction->t_tid; jbd_debug(1, "woke because of timeout\n"); } goto loop; end_loop: spin_unlock(&journal->j_state_lock); del_timer_sync(&journal->j_commit_timer); journal->j_task = NULL; wake_up(&journal->j_wait_done_commit); jbd_debug(1, "Journal thread exiting.\n"); return 0; }