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

📄 revoke.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
							  bh2->b_state));			__brelse(bh2);		}	}#endif	/* We really ought not ever to revoke twice in a row without           first having the revoke cancelled: it's illegal to free a           block twice without allocating it in between! */	if (bh) {		J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state));		set_bit(BH_Revoked, &bh->b_state);		set_bit(BH_RevokeValid, &bh->b_state);		if (bh_in) {			BUFFER_TRACE(bh_in, "call journal_forget");			journal_forget(handle, bh_in);		} else {			BUFFER_TRACE(bh, "call brelse");			__brelse(bh);		}	}	lock_journal(journal);	jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);	err = insert_revoke_hash(journal, blocknr,				handle->h_transaction->t_tid);	unlock_journal(journal);	BUFFER_TRACE(bh_in, "exit");	return err;}/* * Cancel an outstanding revoke.  For use only internally by the * journaling code (called from journal_get_write_access). * * We trust the BH_Revoked bit on the buffer if the buffer is already * being journaled: if there is no revoke pending on the buffer, then we * don't do anything here. * * This would break if it were possible for a buffer to be revoked and * discarded, and then reallocated within the same transaction.  In such * a case we would have lost the revoked bit, but when we arrived here * the second time we would still have a pending revoke to cancel.  So, * do not trust the Revoked bit on buffers unless RevokeValid is also * set. * * The caller must have the journal locked. */int journal_cancel_revoke(handle_t *handle, struct journal_head *jh){	struct jbd_revoke_record_s *record;	journal_t *journal = handle->h_transaction->t_journal;	int need_cancel;	int did_revoke = 0;	/* akpm: debug */	struct buffer_head *bh = jh2bh(jh);		jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);	/* Is the existing Revoke bit valid?  If so, we trust it, and	 * only perform the full cancel if the revoke bit is set.  If	 * not, we can't trust the revoke bit, and we need to do the	 * full search for a revoke record. */	if (test_and_set_bit(BH_RevokeValid, &bh->b_state))		need_cancel = (test_and_clear_bit(BH_Revoked, &bh->b_state));	else {		need_cancel = 1;		clear_bit(BH_Revoked, &bh->b_state);	}	if (need_cancel) {		record = find_revoke_record(journal, bh->b_blocknr);		if (record) {			jbd_debug(4, "cancelled existing revoke on "				  "blocknr %lu\n", bh->b_blocknr);			list_del(&record->hash);			kmem_cache_free(revoke_record_cache, record);			did_revoke = 1;		}	}#ifdef JBD_EXPENSIVE_CHECKING	/* There better not be one left behind by now! */	record = find_revoke_record(journal, bh->b_blocknr);	J_ASSERT_JH(jh, record == NULL);#endif	/* Finally, have we just cleared revoke on an unhashed	 * buffer_head?  If so, we'd better make sure we clear the	 * revoked status on any hashed alias too, otherwise the revoke	 * state machine will get very upset later on. */	if (need_cancel && !bh->b_pprev) {		struct buffer_head *bh2;		bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);		if (bh2) {			clear_bit(BH_Revoked, &bh2->b_state);			__brelse(bh2);		}	}		return did_revoke;}/* * Write revoke records to the journal for all entries in the current * revoke hash, deleting the entries as we go. * * Called with the journal lock held. */void journal_write_revoke_records(journal_t *journal, 				  transaction_t *transaction){	struct journal_head *descriptor;	struct jbd_revoke_record_s *record;	struct jbd_revoke_table_s *revoke;	struct list_head *hash_list;	int i, offset, count;	descriptor = NULL; 	offset = 0;	count = 0;	revoke = journal->j_revoke;		for (i = 0; i < revoke->hash_size; i++) {		hash_list = &revoke->hash_table[i];		while (!list_empty(hash_list)) {			record = (struct jbd_revoke_record_s *) 				hash_list->next;			write_one_revoke_record(journal, transaction,						&descriptor, &offset, 						record);			count++;			list_del(&record->hash);			kmem_cache_free(revoke_record_cache, record);		}	}	if (descriptor) 		flush_descriptor(journal, descriptor, offset);	jbd_debug(1, "Wrote %d revoke records\n", count);}/*  * Write out one revoke record.  We need to create a new descriptor * block if the old one is full or if we have not already created one.   */static void write_one_revoke_record(journal_t *journal, 				    transaction_t *transaction,				    struct journal_head **descriptorp, 				    int *offsetp,				    struct jbd_revoke_record_s *record){	struct journal_head *descriptor;	int offset;	journal_header_t *header;	/* If we are already aborting, this all becomes a noop.  We           still need to go round the loop in           journal_write_revoke_records in order to free all of the           revoke records: only the IO to the journal is omitted. */	if (is_journal_aborted(journal))		return;	descriptor = *descriptorp;	offset = *offsetp;	/* Make sure we have a descriptor with space left for the record */	if (descriptor) {		if (offset == journal->j_blocksize) {			flush_descriptor(journal, descriptor, offset);			descriptor = NULL;		}	}		if (!descriptor) {		descriptor = journal_get_descriptor_buffer(journal);		if (!descriptor)			return;		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];		header->h_magic     = htonl(JFS_MAGIC_NUMBER);		header->h_blocktype = htonl(JFS_REVOKE_BLOCK);		header->h_sequence  = htonl(transaction->t_tid);		/* Record it so that we can wait for IO completion later */		JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");		journal_file_buffer(descriptor, transaction, BJ_LogCtl);		offset = sizeof(journal_revoke_header_t);		*descriptorp = descriptor;	}		* ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) = 		htonl(record->blocknr);	offset += 4;	*offsetp = offset;}/*  * Flush a revoke descriptor out to the journal.  If we are aborting, * this is a noop; otherwise we are generating a buffer which needs to * be waited for during commit, so it has to go onto the appropriate * journal buffer list. */static void flush_descriptor(journal_t *journal, 			     struct journal_head *descriptor, 			     int offset){	journal_revoke_header_t *header;	if (is_journal_aborted(journal)) {		JBUFFER_TRACE(descriptor, "brelse");		unlock_buffer(jh2bh(descriptor));		__brelse(jh2bh(descriptor));		return;	}		header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;	header->r_count = htonl(offset);	set_bit(BH_JWrite, &jh2bh(descriptor)->b_state);	{		struct buffer_head *bh = jh2bh(descriptor);		BUFFER_TRACE(bh, "write");		clear_bit(BH_Dirty, &bh->b_state);		bh->b_end_io = journal_end_buffer_io_sync;		submit_bh(WRITE, bh);	}}#endif/*  * Revoke support for recovery. * * Recovery needs to be able to: * *  record all revoke records, including the tid of the latest instance *  of each revoke in the journal * *  check whether a given block in a given transaction should be replayed *  (ie. has not been revoked by a revoke record in that or a subsequent *  transaction) *  *  empty the revoke table after recovery. *//* * First, setting revoke records.  We create a new revoke record for * every block ever revoked in the log as we scan it for recovery, and * we update the existing records if we find multiple revokes for a * single block.  */int journal_set_revoke(journal_t *journal, 		       unsigned long blocknr, 		       tid_t sequence){	struct jbd_revoke_record_s *record;		record = find_revoke_record(journal, blocknr);	if (record) {		/* If we have multiple occurences, only record the		 * latest sequence number in the hashed record */		if (tid_gt(sequence, record->sequence))			record->sequence = sequence;		return 0;	} 	return insert_revoke_hash(journal, blocknr, sequence);}/*  * Test revoke records.  For a given block referenced in the log, has * that block been revoked?  A revoke record with a given transaction * sequence number revokes all blocks in that transaction and earlier * ones, but later transactions still need replayed. */int journal_test_revoke(journal_t *journal, 			unsigned long blocknr,			tid_t sequence){	struct jbd_revoke_record_s *record;		record = find_revoke_record(journal, blocknr);	if (!record)		return 0;	if (tid_gt(sequence, record->sequence))		return 0;	return 1;}/* * Finally, once recovery is over, we need to clear the revoke table so * that it can be reused by the running filesystem. */void journal_clear_revoke(journal_t *journal){	int i;	struct list_head *hash_list;	struct jbd_revoke_record_s *record;	struct jbd_revoke_table_s *revoke;		revoke = journal->j_revoke;		for (i = 0; i < revoke->hash_size; i++) {		hash_list = &revoke->hash_table[i];		while (!list_empty(hash_list)) {			record = (struct jbd_revoke_record_s*) hash_list->next;			list_del(&record->hash);			kmem_cache_free(revoke_record_cache, record);		}	}}

⌨️ 快捷键说明

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