예제 #1
0
transaction_t * get_transaction (journal_t * journal)
{
	transaction_t * transaction;

	J_ASSERT (journal->j_locked);
	
	transaction = kmalloc (sizeof (transaction_t), GFP_KERNEL);
	if (!transaction)
		return NULL;
	
	memset (transaction, 0, sizeof (transaction_t));
	
	transaction->t_journal = journal;
	transaction->t_state = T_RUNNING;
	transaction->t_tid = journal->j_transaction_sequence++;
	transaction->t_expires = jiffies + journal->j_commit_interval;

	/* Set up the commit timer for the new transaction. */
	J_ASSERT (!journal->j_commit_timer_active);
	journal->j_commit_timer_active = 1;
	journal->j_commit_timer->expires = transaction->t_expires;
	add_timer(journal->j_commit_timer);
	
	J_ASSERT (journal->j_running_transaction == NULL);
	journal->j_running_transaction = transaction;

	return transaction;
}
예제 #2
0
int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
{
	transaction_t *transaction = handle->h_transaction;
	journal_t *journal = transaction->t_journal;
	tid_t		tid;
	int		need_to_start, ret;

	if (is_handle_aborted(handle))
		return 0;

	J_ASSERT(atomic_read(&transaction->t_updates) > 0);
	J_ASSERT(journal_current_handle() == handle);

	read_lock(&journal->j_state_lock);
	spin_lock(&transaction->t_handle_lock);
	atomic_sub(handle->h_buffer_credits,
		   &transaction->t_outstanding_credits);
	if (atomic_dec_and_test(&transaction->t_updates))
		wake_up(&journal->j_wait_updates);
	spin_unlock(&transaction->t_handle_lock);

	jbd_debug(2, "restarting handle %p\n", handle);
	tid = transaction->t_tid;
	need_to_start = !tid_geq(journal->j_commit_request, tid);
	read_unlock(&journal->j_state_lock);
	if (need_to_start)
		jbd2_log_start_commit(journal, tid);

	lock_map_release(&handle->h_lockdep_map);
	handle->h_buffer_credits = nblocks;
	ret = start_this_handle(journal, handle, gfp_mask);
	return ret;
}
예제 #3
0
void journal_refile_buffer(struct buffer_head *bh)
{
#ifdef __SMP__
	J_ASSERT (current->lock_depth >= 0);
#endif
	journal_unfile_buffer(bh);

	/* If the buffer is now unused, just drop it.  If it has been
	   modified by a later transaction, add it to the new
	   transaction's metadata list. */

	bh->b_transaction = bh->b_next_transaction;
	bh->b_next_transaction = NULL;
	
	if (bh->b_transaction != NULL) {
		int tstate;
		journal_file_buffer(bh, bh->b_transaction, BJ_Metadata);
		tstate = bh->b_transaction->t_state;
		J_ASSERT(tstate == T_RUNNING);
	}
		
	/* If necessary, remove it from the global journaled
	   buffer list and replace it back on the main dirty
	   buffer list. */
	refile_buffer(bh);
}
예제 #4
0
파일: revoke.c 프로젝트: AlexShiLucky/linux
/* Initialise the revoke table for a given journal to a given size. */
int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
{
	J_ASSERT(journal->j_revoke_table[0] == NULL);
	J_ASSERT(is_power_of_2(hash_size));

	journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size);
	if (!journal->j_revoke_table[0])
		goto fail0;

	journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size);
	if (!journal->j_revoke_table[1])
		goto fail1;

	journal->j_revoke = journal->j_revoke_table[1];

	spin_lock_init(&journal->j_revoke_lock);

	return 0;

fail1:
	jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
	journal->j_revoke_table[0] = NULL;
fail0:
	return -ENOMEM;
}
예제 #5
0
파일: replay.c 프로젝트: Axure/Ext3Fsd
/**
 *  journal_t * journal_init_inode () - creates a journal which maps to a inode.
 *  @inode: An inode to create the journal in
 *
 * journal_init_inode creates a journal which maps an on-disk inode as
 * the journal.  The inode must exist already, must support bmap() and
 * must have all data blocks preallocated.
 */
journal_t * journal_init_inode (struct inode *inode)
{
    struct buffer_head *bh;
    journal_t *journal = journal_init_common();
    int err;
    int n;
    unsigned long blocknr;

    if (!journal)
        return NULL;

    journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev;
    journal->j_inode = inode;
    jbd_debug(1,
              "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
              journal, inode->i_sb->s_id, inode->i_ino,
              (s64) inode->i_size,
              inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);

    journal->j_maxlen = (unsigned int)(inode->i_size >> inode->i_sb->s_blocksize_bits);
    journal->j_blocksize = inode->i_sb->s_blocksize;

    /* journal descriptor can store up to n blocks -bzzz */
    n = journal->j_blocksize / sizeof(journal_block_tag_t);
    journal->j_wbufsize = n;
    journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
    if (!journal->j_wbuf) {
        printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
               __FUNCTION__);

        J_ASSERT(journal->j_revoke != NULL);
        if (journal->j_revoke)
            journal_destroy_revoke(journal);

        kfree(journal);
        return NULL;
    }

    err = journal_bmap(journal, 0, &blocknr);
    /* If that failed, give up */
    if (err) {
        printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
               __FUNCTION__);

        J_ASSERT(journal->j_revoke != NULL);
        if (journal->j_revoke)
            journal_destroy_revoke(journal);
        J_ASSERT(journal->j_wbuf != NULL);
        kfree(journal->j_wbuf);
        kfree(journal);
        return NULL;
    }

    bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
    J_ASSERT(bh != NULL);
    journal->j_sb_buffer = bh;
    journal->j_superblock = (journal_superblock_t *)bh->b_data;

    return journal;
}
예제 #6
0
int journal_dirty_data (handle_t *handle, struct buffer_head *bh)
{
	journal_t *journal = handle->h_transaction->t_journal;
	lock_journal(journal);

	mark_buffer_dirty(bh, 0);
	
	/*
	 * What if the buffer is already part of a running transaction?
	 * 
	 * There are two cases:
	 * 1) It is part of the current running transaction.  Refile it,
	 *    just in case we have allocated it as metadata, deallocated
	 *    it, then reallocated it as data. 
	 * 2) It is part of the previous, still-committing transaction.
	 *    If all we want to do is to guarantee that the buffer will be
	 *    written to disk before this new transaction commits, then
	 *    being sure that the *previous* transaction has this same 
	 *    property is sufficient for us!  Just leave it on its old
	 *    transaction.
	 *
	 * In case (2), the buffer must not already exist as metadata
	 * --- that would violate write ordering (a transaction is free
	 * to write its data at any point, even before the previous
	 * committing transaction has committed).  The caller must
	 * never, ever allow this to happen: there's nothing we can do
	 * about it in this layer.
	 */

	if (bh->b_transaction) {
		if (bh->b_transaction != handle->h_transaction) {
			J_ASSERT (bh->b_transaction == journal->j_committing_transaction);

			/* @@@ IS THIS TRUE  ? */
			J_ASSERT (bh->b_next_transaction == NULL);

			/* Special case --- the buffer might actually
                           have been allocated and then immediately
                           deallocated in the previous, committing
                           transaction, so might still be left on that
                           transaction's metadata lists. */
			if (bh->b_jlist != BJ_Data) {
				J_ASSERT (bh->b_jlist != BJ_Shadow);
				J_ASSERT (test_and_clear_bit(BH_QuickFree, &bh->b_state));
				journal_unfile_buffer(bh);
				bh->b_transaction = NULL;
				journal_file_buffer(bh, handle->h_transaction, BJ_Data);
				refile_buffer(bh);
			}
		}
	} else {
		journal_file_buffer(bh, handle->h_transaction, BJ_Data);
		refile_buffer(bh);
	}
	
	unlock_journal(journal);
	return 0;
}
예제 #7
0
int journal_stop (handle_t *handle)
{
	transaction_t *transaction = handle->h_transaction;
	journal_t *journal = transaction->t_journal;
	int force_sync;
	
	if (!handle)
		return 0;
	
	J_ASSERT (transaction->t_updates > 0);
	J_ASSERT (current->j_handle == handle);
	
	if (--handle->h_ref > 0)
		return 0;

	jfs_debug(4, "Handle %p going down\n", handle);
	
	current->j_handle = NULL;
	// current->fs_locks--;
	transaction->t_outstanding_credits -= handle->h_buffer_credits;
	transaction->t_updates--;
	if (!transaction->t_updates) {
		wake_up(&journal->j_wait_updates);
		if (journal->j_barrier_count)
			wake_up(&journal->j_wait_transaction_locked);
	}

	/* 
	 * If the journal is marked SYNC, we need to set another commit
	 * going!  We also want to force a commit if the current
	 * transaction is occupying too much of the log, or if the
	 * transaction is too old now.
	 */

	force_sync = (journal->j_flags & JFS_SYNC) || handle->h_sync;
	
	if (force_sync ||
	    transaction->t_outstanding_credits > journal->j_max_transaction_buffers ||
	    time_after_eq(jiffies, transaction->t_expires)) {
		tid_t tid = transaction->t_tid;
		
		jfs_debug(2, "transaction too old, requesting commit for handle %p\n", handle);
		log_start_commit(journal, transaction);
		
		/*
		 * Special case: JFS_SYNC synchronous updates require us
		 * to wait for the commit to complete.  
		 */
		if (force_sync) 
			log_wait_commit(journal, tid);
	}
	
	kfree(handle);
	
	return 0;
}
예제 #8
0
파일: checkpoint.c 프로젝트: 020gzh/linux
void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction)
{
	assert_spin_locked(&journal->j_list_lock);
	if (transaction->t_cpnext) {
		transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
		transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
		if (journal->j_checkpoint_transactions == transaction)
			journal->j_checkpoint_transactions =
				transaction->t_cpnext;
		if (journal->j_checkpoint_transactions == transaction)
			journal->j_checkpoint_transactions = NULL;
	}

	J_ASSERT(transaction->t_state == T_FINISHED);
	J_ASSERT(transaction->t_buffers == NULL);
	J_ASSERT(transaction->t_forget == NULL);
	J_ASSERT(transaction->t_shadow_list == NULL);
	J_ASSERT(transaction->t_checkpoint_list == NULL);
	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
	J_ASSERT(atomic_read(&transaction->t_updates) == 0);
	J_ASSERT(journal->j_committing_transaction != transaction);
	J_ASSERT(journal->j_running_transaction != transaction);

	trace_jbd2_drop_transaction(journal, transaction);

	jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
}
예제 #9
0
void journal_unfile_buffer(struct buffer_head *buf)
{
	struct buffer_head **list = 0;
	transaction_t * transaction;

	transaction = buf->b_transaction;
	
#ifdef __SMP__
	J_ASSERT (current->lock_depth >= 0);
#endif
	J_ASSERT (transaction->t_journal->j_locked);
	J_ASSERT (buf->b_jlist < BJ_Types);
	
	if (buf->b_jlist != BJ_None)
		J_ASSERT (transaction != 0);
	
	switch (buf->b_jlist) {
	case BJ_None:
		return;
	case BJ_Data:
		list = &transaction->t_datalist;
		break;
	case BJ_Metadata:
		transaction->t_nr_buffers--;
		J_ASSERT(transaction->t_nr_buffers >= 0);
		list = &transaction->t_buffers;
		break;
	case BJ_Forget:
		list = &transaction->t_forget;
		break;
	case BJ_IO:
		list = &transaction->t_iobuf_list;
		break;
	case BJ_Shadow:
		list = &transaction->t_shadow_list;
		break;
	case BJ_LogCtl:
		list = &transaction->t_log_list;
		break;
	case BJ_Reserved:
		list = &transaction->t_reserved_list;
		break;
	}
	
	blist_del_buffer(list, buf);
	buf->b_jlist = BJ_None;
	if (buffer_jdirty(buf)) {
		set_bit(BH_Dirty, &buf->b_state);
		clear_bit(BH_JDirty, &buf->b_state);
	}
}
예제 #10
0
int jbd2_cleanup_journal_tail(journal_t *journal)
{
	tid_t		first_tid;
	unsigned long	blocknr;

	if (is_journal_aborted(journal))
		return 1;

	if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr))
		return 1;
	J_ASSERT(blocknr != 0);

	/*
                                                                       
                                                                      
                                                                      
                                                                        
                                                    
                                                                  
  */
	if (journal->j_flags & JBD2_BARRIER)
		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);

	__jbd2_update_log_tail(journal, first_tid, blocknr);
	return 0;
}
예제 #11
0
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
{
	struct inode *inode = dentry->d_inode;
	int ret;

	J_ASSERT(ext3_journal_current_handle() == 0);

	/*
	 * fsync_inode_buffers() just walks i_dirty_buffers and waits
	 * on them.  It's a no-op for full data journalling because
	 * i_dirty_buffers will be ampty.
	 * Really, we only need to start I/O on the dirty buffers -
	 * we'll end up waiting on them in commit.
	 */
	ret = fsync_inode_buffers(inode);

	/* In writeback mode, we need to force out data buffers too.  In
	 * the other modes, ext3_force_commit takes care of forcing out
	 * just the right data blocks. */
	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
		ret |= fsync_inode_data_buffers(inode);

	ext3_force_commit(inode->i_sb);

	return ret;
}
예제 #12
0
int jbd2_journal_try_to_free_buffers(journal_t *journal,
				struct page *page, gfp_t gfp_mask)
{
	struct buffer_head *head;
	struct buffer_head *bh;
	int ret = 0;

	J_ASSERT(PageLocked(page));

	head = page_buffers(page);
	bh = head;
	do {
		struct journal_head *jh;

		jh = jbd2_journal_grab_journal_head(bh);
		if (!jh)
			continue;

		jbd_lock_bh_state(bh);
		__journal_try_to_free_buffer(journal, bh);
		jbd2_journal_put_journal_head(jh);
		jbd_unlock_bh_state(bh);
		if (buffer_jbd(bh))
			goto busy;
	} while ((bh = bh->b_this_page) != head);

	ret = try_to_free_buffers(page);

busy:
	return ret;
}
예제 #13
0
int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
{
	struct inode *inode = file->f_mapping->host;
	struct ext3_inode_info *ei = EXT3_I(inode);
	journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
	int ret, needs_barrier = 0;
	tid_t commit_tid;

	trace_ext3_sync_file_enter(file, datasync);

	if (inode->i_sb->s_flags & MS_RDONLY)
		return 0;

	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
	if (ret)
		goto out;

	J_ASSERT(ext3_journal_current_handle() == NULL);

	/*
	 * data=writeback,ordered:
	 *  The caller's filemap_fdatawrite()/wait will sync the data.
	 *  Metadata is in the journal, we wait for a proper transaction
	 *  to commit here.
	 *
	 * data=journal:
	 *  filemap_fdatawrite won't do anything (the buffers are clean).
	 *  ext3_force_commit will write the file data into the journal and
	 *  will wait on that.
	 *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
	 *  (they were dirtied by commit).  But that's OK - the blocks are
	 *  safe in-journal, which is all fsync() needs to ensure.
	 */
	if (ext3_should_journal_data(inode)) {
		ret = ext3_force_commit(inode->i_sb);
		goto out;
	}

	if (datasync)
		commit_tid = atomic_read(&ei->i_datasync_tid);
	else
		commit_tid = atomic_read(&ei->i_sync_tid);

	if (test_opt(inode->i_sb, BARRIER) &&
	    !journal_trans_will_send_data_barrier(journal, commit_tid))
		needs_barrier = 1;
	log_start_commit(journal, commit_tid);
	ret = log_wait_commit(journal, commit_tid);

	/*
	 * In case we didn't commit a transaction, we have to flush
	 * disk caches manually so that data really is on persistent
	 * storage
	 */
	if (needs_barrier)
		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
out:
	trace_ext3_sync_file_exit(inode, ret);
	return ret;
}
예제 #14
0
static transaction_t *
jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
{
	transaction->t_journal = journal;
	transaction->t_state = T_RUNNING;
	transaction->t_start_time = ktime_get();
	transaction->t_tid = journal->j_transaction_sequence++;
	transaction->t_expires = jiffies + journal->j_commit_interval;
	spin_lock_init(&transaction->t_handle_lock);
	atomic_set(&transaction->t_updates, 0);
	atomic_set(&transaction->t_outstanding_credits, 0);
	atomic_set(&transaction->t_handle_count, 0);
	INIT_LIST_HEAD(&transaction->t_inode_list);
	INIT_LIST_HEAD(&transaction->t_private_list);

	
	journal->j_commit_timer.expires = round_jiffies_up(transaction->t_expires);
	add_timer(&journal->j_commit_timer);

	J_ASSERT(journal->j_running_transaction == NULL);
	journal->j_running_transaction = transaction;
	transaction->t_max_wait = 0;
	transaction->t_start = jiffies;

	return transaction;
}
예제 #15
0
파일: replay.c 프로젝트: Axure/Ext3Fsd
int journal_wipe(journal_t *journal, int write)
{
    journal_superblock_t *sb;
    int err = 0;

    J_ASSERT (!(journal->j_flags & JFS_LOADED));

    err = load_superblock(journal);
    if (err)
        return err;

    sb = journal->j_superblock;

    if (!journal->j_tail)
        goto no_recovery;

    printk (KERN_WARNING "JBD: %s recovery information on journal\n",
            write ? "Clearing" : "Ignoring");

    err = journal_skip_recovery(journal);
    if (write)
        journal_update_superblock(journal, 1);

no_recovery:
    return err;
}
예제 #16
0
파일: checkpoint.c 프로젝트: 020gzh/linux
int jbd2_cleanup_journal_tail(journal_t *journal)
{
	tid_t		first_tid;
	unsigned long	blocknr;

	if (is_journal_aborted(journal))
		return -EIO;

	if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr))
		return 1;
	J_ASSERT(blocknr != 0);

	/*
	 * We need to make sure that any blocks that were recently written out
	 * --- perhaps by jbd2_log_do_checkpoint() --- are flushed out before
	 * we drop the transactions from the journal. It's unlikely this will
	 * be necessary, especially with an appropriately sized journal, but we
	 * need this to guarantee correctness.  Fortunately
	 * jbd2_cleanup_journal_tail() doesn't get called all that often.
	 */
	if (journal->j_flags & JBD2_BARRIER)
		blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);

	return __jbd2_update_log_tail(journal, first_tid, blocknr);
}
예제 #17
0
handle_t *journal_start(journal_t *journal, int nblocks)
{
	handle_t *handle = journal_current_handle();
	int err;

	if (!journal)
		return ERR_PTR(-EROFS);

	if (handle) {
		J_ASSERT(handle->h_transaction->t_journal == journal);
		handle->h_ref++;
		return handle;
	}

	handle = new_handle(nblocks);
	if (!handle)
		return ERR_PTR(-ENOMEM);

	current->journal_info = handle;

	err = start_this_handle(journal, handle);
	if (err < 0) {
		jbd_free_handle(handle);
		current->journal_info = NULL;
		handle = ERR_PTR(err);
		goto out;
	}
out:
	return handle;
}
예제 #18
0
void jbd2_journal_invalidatepage(journal_t *journal,
		      struct page *page,
		      unsigned long offset)
{
	struct buffer_head *head, *bh, *next;
	unsigned int curr_off = 0;
	int may_free = 1;

	if (!PageLocked(page))
		BUG();
	if (!page_has_buffers(page))
		return;


	head = bh = page_buffers(page);
	do {
		unsigned int next_off = curr_off + bh->b_size;
		next = bh->b_this_page;

		if (offset <= curr_off) {
			
			lock_buffer(bh);
			may_free &= journal_unmap_buffer(journal, bh);
			unlock_buffer(bh);
		}
		curr_off = next_off;
		bh = next;

	} while (bh != head);

	if (!offset) {
		if (may_free && try_to_free_buffers(page))
			J_ASSERT(!page_has_buffers(page));
	}
}
예제 #19
0
void hm_async_queue_push_unlocked(JAsyncQueue *queue, void *data)
{
	J_ASSERT(queue != NULL && data != NULL);

	hm_queue_push_tail(&queue->queue, data);
	hm_cond_signal(queue->cond);
}
예제 #20
0
int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
{
	journal_t *journal = handle->h_transaction->t_journal;
	int err;

	lock_journal_bh_wait(bh, journal);

	/* Do this first --- it can drop the journal lock, so we want to
	 * make sure that obtaining the committed_data is done
	 * atomically wrt. completion of any outstanding commits. */
	err = do_get_write_access (handle, bh, 1);

	if (!bh->b_committed_data) {

		/* Copy out the current buffer contents into the
		 * preserved, committed copy. */

		bh->b_committed_data = kmalloc(bh->b_size, GFP_KERNEL);
		if (!bh->b_committed_data) {
			unlock_journal(journal);
			return -ENOMEM;
		}
		
		memcpy (bh->b_committed_data, bh->b_data, bh->b_size);
	}
	
	unlock_journal(journal);
	if (!err)
		J_ASSERT(bh->b_committed_data);
	return err;
}
예제 #21
0
JAsyncQueue *hm_async_queue_ref(JAsyncQueue *queue)
{
	J_ASSERT(queue != NULL);

	atomic_inc(&queue->ref_count);
	return queue;
}
예제 #22
0
int cleanup_journal_tail(journal_t *journal)
{
	transaction_t * transaction;
	tid_t		first_tid;
	unsigned long	blocknr, freed;

	/* OK, work out the oldest transaction remaining in the log, and
	 * the log block it starts at. 
	 * 
	 * If the log is now empty, we need to work out which is the
	 * next transaction ID we will write, and where it will
	 * start. */

	spin_lock(&journal->j_state_lock);
	spin_lock(&journal->j_list_lock);
	transaction = journal->j_checkpoint_transactions;
	if (transaction) {
		first_tid = transaction->t_tid;
		blocknr = transaction->t_log_start;
	} else if ((transaction = journal->j_committing_transaction) != NULL) {
		first_tid = transaction->t_tid;
		blocknr = transaction->t_log_start;
	} else if ((transaction = journal->j_running_transaction) != NULL) {
		first_tid = transaction->t_tid;
		blocknr = journal->j_head;
	} else {
		first_tid = journal->j_transaction_sequence;
		blocknr = journal->j_head;
	}
	spin_unlock(&journal->j_list_lock);
	J_ASSERT(blocknr != 0);

	/* If the oldest pinned transaction is at the tail of the log
           already then there's not much we can do right now. */
	if (journal->j_tail_sequence == first_tid) {
		spin_unlock(&journal->j_state_lock);
		return 1;
	}

	/* OK, update the superblock to recover the freed space.
	 * Physical blocks come first: have we wrapped beyond the end of
	 * the log?  */
	freed = blocknr - journal->j_tail;
	if (blocknr < journal->j_tail)
		freed = freed + journal->j_last - journal->j_first;

	jbd_debug(1,
		  "Cleaning journal tail from %d to %d (offset %lu), "
		  "freeing %lu\n",
		  journal->j_tail_sequence, first_tid, blocknr, freed);

	journal->j_free += freed;
	journal->j_tail_sequence = first_tid;
	journal->j_tail = blocknr;
	spin_unlock(&journal->j_state_lock);
	if (!(journal->j_flags & JFS_ABORT))
		journal_update_superblock(journal, 1);
	return 0;
}
예제 #23
0
void hm_thread_pool_push(JThreadPool *tp, void *data)
{
    JRealThreadPool *_tp;
    J_ASSERT(tp != NULL && data != NULL);

    _tp = (JRealThreadPool*)tp;
    hm_async_queue_push(_tp->queue, data);
}
예제 #24
0
void hm_async_queue_push(JAsyncQueue *queue, void *data)
{
	J_ASSERT(queue != NULL);

	hm_mutex_lock(queue->mutex);
	hm_async_queue_push_unlocked(queue, data);
	hm_mutex_unlock(queue->mutex);
}
예제 #25
0
/*
 * Release a JNetRealBuf object.
*/
__export void
hm_net_buf_free(JNetBuf *buf)
{
    J_ASSERT(buf != NULL);

    hm_mutex_free(buf->buf_lock);
	hm_dealloc(buf, buf->object_size);
}
예제 #26
0
파일: fsync.c 프로젝트: 710leo/LVS
int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
{
	struct inode *inode = dentry->d_inode;
	struct ext4_inode_info *ei = EXT4_I(inode);
	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
	int ret;
	tid_t commit_tid;

	J_ASSERT(ext4_journal_current_handle() == NULL);

	trace_ext4_sync_file(file, dentry, datasync);

	if (inode->i_sb->s_flags & MS_RDONLY)
		return 0;

	ret = flush_aio_dio_completed_IO(inode);
	if (ret < 0)
		return ret;

	if (!journal)
		return simple_fsync(file, dentry, datasync);

	/*
	 * data=writeback,ordered:
	 *  The caller's filemap_fdatawrite()/wait will sync the data.
	 *  Metadata is in the journal, we wait for proper transaction to
	 *  commit here.
	 *
	 * data=journal:
	 *  filemap_fdatawrite won't do anything (the buffers are clean).
	 *  ext4_force_commit will write the file data into the journal and
	 *  will wait on that.
	 *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
	 *  (they were dirtied by commit).  But that's OK - the blocks are
	 *  safe in-journal, which is all fsync() needs to ensure.
	 */
	if (ext4_should_journal_data(inode))
		return ext4_force_commit(inode->i_sb);

	commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
	if (jbd2_log_start_commit(journal, commit_tid)) {
		/*
		 * When the journal is on a different device than the
		 * fs data disk, we need to issue the barrier in
		 * writeback mode.  (In ordered mode, the jbd2 layer
		 * will take care of issuing the barrier.  In
		 * data=journal, all of the data blocks are written to
		 * the journal device.)
		 */
		if (ext4_should_writeback_data(inode) &&
		    (journal->j_fs_dev != journal->j_dev) &&
		    (journal->j_flags & JBD2_BARRIER))
			blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
		ret = jbd2_log_wait_commit(journal, commit_tid);
	} else if (journal->j_flags & JBD2_BARRIER)
		blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
	return ret;
}
예제 #27
0
/**
 * pause the play, return true if current are playing
 * */
bool OpenSLIn::pause(){
	J_ASSERT(mState == SLIN_PAUSE || mState == SLIN_RECORD);

	tryCallBack(WHEN_PAUSE, &mState);

	if(mState == SLIN_PAUSE){
		// goto record
		mState = SLIN_RECORD;
	}else if(mState == SLIN_RECORD){
		// goto pause
		mState = SLIN_PAUSE;
		return true;
	}else {
		J_ASSERT(false);
	}

	return false;
}
예제 #28
0
/**
 * stop the play
 * */
void OpenSLIn::stop(){
	J_ASSERT(mState != SLIN_STOP);

	tryCallBack(WHEN_STOP, 0);

	mState = SLIN_STOP;
	stopInternal();
	return;
}
예제 #29
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);
}
예제 #30
0
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
{
	struct inode *inode = dentry->d_inode;
	int ret = 0;

	J_ASSERT(ext3_journal_current_handle() == 0);

	/*
	 * data=writeback:
	 *  The caller's filemap_fdatawrite()/wait will sync the data.
	 *  sync_inode() will sync the metadata
	 *
	 * data=ordered:
	 *  The caller's filemap_fdatawrite() will write the data and
	 *  sync_inode() will write the inode if it is dirty.  Then the caller's
	 *  filemap_fdatawait() will wait on the pages.
	 *
	 * data=journal:
	 *  filemap_fdatawrite won't do anything (the buffers are clean).
	 *  ext3_force_commit will write the file data into the journal and
	 *  will wait on that.
	 *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
	 *  (they were dirtied by commit).  But that's OK - the blocks are
	 *  safe in-journal, which is all fsync() needs to ensure.
	 */
	if (ext3_should_journal_data(inode)) {
		ret = ext3_force_commit(inode->i_sb);
		goto out;
	}

	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
		goto flush;

	/*
	 * The VFS has written the file data.  If the inode is unaltered
	 * then we need not start a commit.
	 */
	if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) {
		struct writeback_control wbc = {
			.sync_mode = WB_SYNC_ALL,
			.nr_to_write = 0, /* sys_fsync did this */
		};
		ret = sync_inode(inode, &wbc);
		goto out;
	}
flush:
	/*
	 * In case we didn't commit a transaction, we have to flush
	 * disk caches manually so that data really is on persistent
	 * storage
	 */
	if (test_opt(inode->i_sb, BARRIER))
		blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
out:
	return ret;
}