⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 checkpoint.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
		int drop_count = 0;		int cleanup_ret, retry = 0;		transaction = next_transaction;		next_transaction = transaction->t_cpnext;		jh = transaction->t_checkpoint_list;		last_jh = jh->b_cpprev;		next_jh = jh;		do {			jh = next_jh;			next_jh = jh->b_cpnext;			retry = __flush_buffer(journal, jh, bhs, &batch_count,						&drop_count);		} while (jh != last_jh && !retry);		if (batch_count) {			__flush_batch(bhs, &batch_count);			goto repeat;		}		if (retry)			goto repeat;		/*		 * We have walked the whole transaction list without		 * finding anything to write to disk.  We had better be		 * able to make some progress or we are in trouble. 		 */		cleanup_ret = __cleanup_transaction(journal, transaction);		J_ASSERT(drop_count != 0 || cleanup_ret != 0);		goto repeat;	/* __cleanup may have dropped lock */	} while (transaction != last_transaction);done:	spin_unlock(&journal_datalist_lock);	result = cleanup_journal_tail(journal);	if (result < 0)		return result;		return 0;}/* * Check the list of checkpoint transactions for the journal to see if * we have already got rid of any since the last update of the log tail * in the journal superblock.  If so, we can instantly roll the * superblock forward to remove those transactions from the log. *  * Return <0 on error, 0 on success, 1 if there was nothing to clean up. *  * Called with the journal lock held. * * This is the only part of the journaling code which really needs to be * aware of transaction aborts.  Checkpointing involves writing to the * main filesystem area rather than to the journal, so it can proceed * even in abort state, but we must not update the journal superblock if * we have an abort error outstanding. */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. */	/* j_checkpoint_transactions needs locking */	spin_lock(&journal_datalist_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_datalist_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)		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;	if (!(journal->j_flags & JFS_ABORT))		journal_update_superblock(journal, 1);	return 0;}/* Checkpoint list management *//* * journal_clean_checkpoint_list * * Find all the written-back checkpoint buffers in the journal and release them. * * Called with the journal locked. * Called with journal_datalist_lock held. * Returns number of bufers reaped (for debug) */int __journal_clean_checkpoint_list(journal_t *journal){	transaction_t *transaction, *last_transaction, *next_transaction;	int ret = 0;	transaction = journal->j_checkpoint_transactions;	if (transaction == 0)		goto out;	last_transaction = transaction->t_cpprev;	next_transaction = transaction;	do {		struct journal_head *jh;		transaction = next_transaction;		next_transaction = transaction->t_cpnext;		jh = transaction->t_checkpoint_list;		if (jh) {			struct journal_head *last_jh = jh->b_cpprev;			struct journal_head *next_jh = jh;			do {				jh = next_jh;				next_jh = jh->b_cpnext;				ret += __try_to_free_cp_buf(jh);			} while (jh != last_jh);		}	} while (transaction != last_transaction);out:	return ret;}/*  * journal_remove_checkpoint: called after a buffer has been committed * to disk (either by being write-back flushed to disk, or being * committed to the log). * * We cannot safely clean a transaction out of the log until all of the * buffer updates committed in that transaction have safely been stored * elsewhere on disk.  To achieve this, all of the buffers in a * transaction need to be maintained on the transaction's checkpoint * list until they have been rewritten, at which point this function is * called to remove the buffer from the existing transaction's * checkpoint list.   * * This function is called with the journal locked. * This function is called with journal_datalist_lock held. */void __journal_remove_checkpoint(struct journal_head *jh){	transaction_t *transaction;	journal_t *journal;	JBUFFER_TRACE(jh, "entry");		if ((transaction = jh->b_cp_transaction) == NULL) {		JBUFFER_TRACE(jh, "not on transaction");		goto out;	}	journal = transaction->t_journal;	__buffer_unlink(jh);	if (transaction->t_checkpoint_list != NULL)		goto out;	JBUFFER_TRACE(jh, "transaction has no more buffers");	/* There is one special case to worry about: if we have just           pulled the buffer off a committing transaction's forget list,           then even if the checkpoint list is empty, the transaction           obviously cannot be dropped! */	if (transaction == journal->j_committing_transaction) {		JBUFFER_TRACE(jh, "belongs to committing transaction");		goto out;	}	/* OK, that was the last buffer for the transaction: we can now	   safely remove this transaction from the log */	__journal_drop_transaction(journal, transaction);	/* Just in case anybody was waiting for more transactions to be           checkpointed... */	wake_up(&journal->j_wait_logspace);out:	JBUFFER_TRACE(jh, "exit");}void journal_remove_checkpoint(struct journal_head *jh){	spin_lock(&journal_datalist_lock);	__journal_remove_checkpoint(jh);	spin_unlock(&journal_datalist_lock);}/* * journal_insert_checkpoint: put a committed buffer onto a checkpoint * list so that we know when it is safe to clean the transaction out of * the log. * * Called with the journal locked. * Called with journal_datalist_lock held. */void __journal_insert_checkpoint(struct journal_head *jh, 			       transaction_t *transaction){	JBUFFER_TRACE(jh, "entry");	J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jdirty(jh2bh(jh)));	J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);	assert_spin_locked(&journal_datalist_lock);	jh->b_cp_transaction = transaction;	if (!transaction->t_checkpoint_list) {		jh->b_cpnext = jh->b_cpprev = jh;	} else {		jh->b_cpnext = transaction->t_checkpoint_list;		jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;		jh->b_cpprev->b_cpnext = jh;		jh->b_cpnext->b_cpprev = jh;	}	transaction->t_checkpoint_list = jh;}void journal_insert_checkpoint(struct journal_head *jh, 			       transaction_t *transaction){	spin_lock(&journal_datalist_lock);	__journal_insert_checkpoint(jh, transaction);	spin_unlock(&journal_datalist_lock);}/* * We've finished with this transaction structure: adios... *  * The transaction must have no links except for the checkpoint by this * point. * * Called with the journal locked. * Called with journal_datalist_lock held. */void __journal_drop_transaction(journal_t *journal, transaction_t *transaction){	assert_spin_locked(&journal_datalist_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_ilist == NULL);	J_ASSERT (transaction->t_buffers == NULL);	J_ASSERT (transaction->t_sync_datalist == NULL);	J_ASSERT (transaction->t_async_datalist == NULL);	J_ASSERT (transaction->t_forget == NULL);	J_ASSERT (transaction->t_iobuf_list == NULL);	J_ASSERT (transaction->t_shadow_list == NULL);	J_ASSERT (transaction->t_log_list == NULL);	J_ASSERT (transaction->t_checkpoint_list == NULL);	J_ASSERT (transaction->t_updates == 0);		J_ASSERT (transaction->t_journal->j_committing_transaction !=					transaction);		jbd_debug (1, "Dropping transaction %d, all done\n", 		   transaction->t_tid);	kfree (transaction);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -