/*
 * __log_wait_for_space: wait until there is space in the journal.
 *
 * Called under j-state_lock *only*.  It will be unlocked if we have to wait
 * for a checkpoint to free up some space in the log.
 */
void __log_wait_for_space(journal_t *journal)
{
	int nblocks;
	assert_spin_locked(&journal->j_state_lock);

	nblocks = jbd_space_needed(journal);
	while (__log_space_left(journal) < nblocks) {
		if (journal->j_flags & JFS_ABORT)
			return;
		spin_unlock(&journal->j_state_lock);
		mutex_lock(&journal->j_checkpoint_mutex);

		/*
		 * Test again, another process may have checkpointed while we
		 * were waiting for the checkpoint lock
		 */
		spin_lock(&journal->j_state_lock);
		nblocks = jbd_space_needed(journal);
		if (__log_space_left(journal) < nblocks) {
			spin_unlock(&journal->j_state_lock);
			log_do_checkpoint(journal);
			spin_lock(&journal->j_state_lock);
		}
		mutex_unlock(&journal->j_checkpoint_mutex);
	}
}
예제 #2
0
/*
 * __log_wait_for_space: wait until there is space in the journal.
 *
 * Called under j-state_lock *only*.  It will be unlocked if we have to wait
 * for a checkpoint to free up some space in the log.
 */
void __log_wait_for_space(journal_t *journal)
{
	int nblocks, space_left;
	assert_spin_locked(&journal->j_state_lock);

	nblocks = jbd_space_needed(journal);
	while (__log_space_left(journal) < nblocks) {
		if (journal->j_flags & JFS_ABORT)
			return;
		spin_unlock(&journal->j_state_lock);
		mutex_lock(&journal->j_checkpoint_mutex);

		/*
		 * Test again, another process may have checkpointed while we
		 * were waiting for the checkpoint lock. If there are no
		 * transactions ready to be checkpointed, try to recover
		 * journal space by calling cleanup_journal_tail(), and if
		 * that doesn't work, by waiting for the currently committing
		 * transaction to complete.  If there is absolutely no way
		 * to make progress, this is either a BUG or corrupted
		 * filesystem, so abort the journal and leave a stack
		 * trace for forensic evidence.
		 */
		spin_lock(&journal->j_state_lock);
		spin_lock(&journal->j_list_lock);
		nblocks = jbd_space_needed(journal);
		space_left = __log_space_left(journal);
		if (space_left < nblocks) {
			int chkpt = journal->j_checkpoint_transactions != NULL;
			tid_t tid = 0;

			if (journal->j_committing_transaction)
				tid = journal->j_committing_transaction->t_tid;
			spin_unlock(&journal->j_list_lock);
			spin_unlock(&journal->j_state_lock);
			if (chkpt) {
				log_do_checkpoint(journal);
			} else if (cleanup_journal_tail(journal) == 0) {
				/* We were able to recover space; yay! */
				;
			} else if (tid) {
				log_wait_commit(journal, tid);
			} else {
				printk(KERN_ERR "%s: needed %d blocks and "
				       "only had %d space available\n",
				       __func__, nblocks, space_left);
				printk(KERN_ERR "%s: no way to get more "
				       "journal space\n", __func__);
				WARN_ON(1);
				journal_abort(journal, 0);
			}
			spin_lock(&journal->j_state_lock);
		} else {
			spin_unlock(&journal->j_list_lock);
		}
		mutex_unlock(&journal->j_checkpoint_mutex);
	}
}
예제 #3
0
void __log_wait_for_space(journal_t *journal)
{
	int nblocks, space_left;
	assert_spin_locked(&journal->j_state_lock);

	nblocks = jbd_space_needed(journal);
	while (__log_space_left(journal) < nblocks) {
		if (journal->j_flags & JFS_ABORT)
			return;
		spin_unlock(&journal->j_state_lock);
		mutex_lock(&journal->j_checkpoint_mutex);

		/*
                                                               
                                                          
                                                          
                                                            
                                                               
                                                            
                                                        
                                                       
                                 
   */
		spin_lock(&journal->j_state_lock);
		spin_lock(&journal->j_list_lock);
		nblocks = jbd_space_needed(journal);
		space_left = __log_space_left(journal);
		if (space_left < nblocks) {
			int chkpt = journal->j_checkpoint_transactions != NULL;
			tid_t tid = 0;

			if (journal->j_committing_transaction)
				tid = journal->j_committing_transaction->t_tid;
			spin_unlock(&journal->j_list_lock);
			spin_unlock(&journal->j_state_lock);
			if (chkpt) {
				log_do_checkpoint(journal);
			} else if (cleanup_journal_tail(journal) == 0) {
				/*                                     */
				;
			} else if (tid) {
				log_wait_commit(journal, tid);
			} else {
				printk(KERN_ERR "%s: needed %d blocks and "
				       "only had %d space available\n",
				       __func__, nblocks, space_left);
				printk(KERN_ERR "%s: no way to get more "
				       "journal space\n", __func__);
				WARN_ON(1);
				journal_abort(journal, 0);
			}
			spin_lock(&journal->j_state_lock);
		} else {
			spin_unlock(&journal->j_list_lock);
		}
		mutex_unlock(&journal->j_checkpoint_mutex);
	}
}
예제 #4
0
파일: checkpoint.c 프로젝트: hugh712/Jollen
void log_wait_for_space(journal_t *journal, int nblocks)
{
	while (log_space_left(journal) < nblocks) {
		if (journal->j_flags & JFS_ABORT)
			return;
		unlock_journal(journal);
		down(&journal->j_checkpoint_sem);
		lock_journal(journal);
		
		/* Test again, another process may have checkpointed
		 * while we were waiting for the checkpoint lock */
		if (log_space_left(journal) < nblocks) {
			log_do_checkpoint(journal, nblocks);
		}
		up(&journal->j_checkpoint_sem);
	}
}
예제 #5
0
파일: replay.c 프로젝트: Axure/Ext3Fsd
/**
 * 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);
}