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

📄 journal.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 4 页
字号:
	new_bh->b_state = 0;	init_buffer(new_bh, NULL, NULL);	atomic_set(&new_bh->b_count, 1);	new_jh = journal_add_journal_head(new_bh);	set_bh_page(new_bh, new_page, new_offset);	new_jh->b_transaction = NULL;	new_bh->b_size = jh2bh(jh_in)->b_size;	new_bh->b_dev = transaction->t_journal->j_dev;	new_bh->b_blocknr = blocknr;	new_bh->b_state |= (1 << BH_Mapped) | (1 << BH_Dirty);	*jh_out = new_jh;	/*	 * Did we need to do an escaping?  Now we've done all the	 * copying, we can finally do so.	 */	if (do_escape)		* ((unsigned int *) mapped_data) = 0;	kunmap(new_page);		/*	 * The to-be-written buffer needs to get moved to the io queue,	 * and the original buffer whose contents we are shadowing or	 * copying is moved to the transaction's shadow queue.	 */	JBUFFER_TRACE(jh_in, "file as BJ_Shadow");	journal_file_buffer(jh_in, transaction, BJ_Shadow);	JBUFFER_TRACE(new_jh, "file as BJ_IO");	journal_file_buffer(new_jh, transaction, BJ_IO);	return do_escape | (done_copy_out << 1);}/* * Allocation code for the journal file.  Manage the space left in the * journal, so that we can begin checkpointing when appropriate. *//* * log_space_left: Return the number of free blocks left in the journal. * * Called with the journal already locked. */int log_space_left (journal_t *journal){	int left = journal->j_free;	/* Be pessimistic here about the number of those free blocks	 * which might be required for log descriptor control blocks. */#define MIN_LOG_RESERVED_BLOCKS 32 /* Allow for rounding errors */	left -= MIN_LOG_RESERVED_BLOCKS;	if (left <= 0)		return 0;	left -= (left >> 3);	return left;}/* * This function must be non-allocating for PF_MEMALLOC tasks */tid_t log_start_commit (journal_t *journal, transaction_t *transaction){	tid_t target = journal->j_commit_request;	lock_kernel(); /* Protect journal->j_running_transaction */		/*	 * A NULL transaction asks us to commit the currently running	 * transaction, if there is one.  	 */	if (transaction)		target = transaction->t_tid;	else {		transaction = journal->j_running_transaction;		if (!transaction)			goto out;		target = transaction->t_tid;	}			/*	 * Are we already doing a recent enough commit?	 */	if (tid_geq(journal->j_commit_request, target))		goto out;	/*	 * We want a new commit: OK, mark the request and wakup the	 * commit thread.  We do _not_ do the commit ourselves.	 */	journal->j_commit_request = target;	jbd_debug(1, "JBD: requesting commit %d/%d\n",		  journal->j_commit_request,		  journal->j_commit_sequence);	wake_up(&journal->j_wait_commit);out:	unlock_kernel();	return target;}/* * Wait for a specified commit to complete. * The caller may not hold the journal lock. */void log_wait_commit (journal_t *journal, tid_t tid){	lock_kernel();#ifdef CONFIG_JBD_DEBUG	lock_journal(journal);	if (!tid_geq(journal->j_commit_request, tid)) {		printk(KERN_EMERG __FUNCTION__			": error: j_commit_request=%d, tid=%d\n",			journal->j_commit_request, tid);	}	unlock_journal(journal);#endif	while (tid_gt(tid, journal->j_commit_sequence)) {		jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n",				  tid, journal->j_commit_sequence);		wake_up(&journal->j_wait_commit);		sleep_on(&journal->j_wait_done_commit);	}	unlock_kernel();}/* * Log buffer allocation routines: */int journal_next_log_block(journal_t *journal, unsigned long *retp){	unsigned long blocknr;	J_ASSERT(journal->j_free > 1);	blocknr = journal->j_head;	journal->j_head++;	journal->j_free--;	if (journal->j_head == journal->j_last)		journal->j_head = journal->j_first;	return journal_bmap(journal, blocknr, retp);}/* * Conversion of logical to physical block numbers for the journal * * On external journals the journal blocks are identity-mapped, so * this is a no-op.  If needed, we can use j_blk_offset - everything is * ready. */int journal_bmap(journal_t *journal, unsigned long blocknr, 		 unsigned long *retp){	int err = 0;	unsigned long ret;	if (journal->j_inode) {		ret = bmap(journal->j_inode, blocknr);		if (ret)			*retp = ret;		else {			printk (KERN_ALERT __FUNCTION__ 				": journal block not found "				"at offset %lu on %s\n",				blocknr, bdevname(journal->j_dev));			err = -EIO;			__journal_abort_soft(journal, err);		}	} else {		*retp = blocknr; /* +journal->j_blk_offset */	}	return err;}/* * We play buffer_head aliasing tricks to write data/metadata blocks to * the journal without copying their contents, but for journal * descriptor blocks we do need to generate bona fide buffers. * * We return a jh whose bh is locked and ready to be populated. */struct journal_head * journal_get_descriptor_buffer(journal_t *journal){	struct buffer_head *bh;	unsigned long blocknr;	int err;	err = journal_next_log_block(journal, &blocknr);	if (err)		return NULL;	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);	lock_buffer(bh);	BUFFER_TRACE(bh, "return this buffer");	return journal_add_journal_head(bh);}/* * Management for journal control blocks: functions to create and * destroy journal_t structures, and to initialise and read existing * journal blocks from disk.  *//* First: create and setup a journal_t object in memory.  We initialise * very few fields yet: that has to wait until we have created the * journal structures from from scratch, or loaded them from disk. */static journal_t * journal_init_common (void){	journal_t *journal;	int err;	MOD_INC_USE_COUNT;	journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);	if (!journal)		goto fail;	memset(journal, 0, sizeof(*journal));	init_waitqueue_head(&journal->j_wait_transaction_locked);	init_waitqueue_head(&journal->j_wait_logspace);	init_waitqueue_head(&journal->j_wait_done_commit);	init_waitqueue_head(&journal->j_wait_checkpoint);	init_waitqueue_head(&journal->j_wait_commit);	init_waitqueue_head(&journal->j_wait_updates);	init_MUTEX(&journal->j_barrier);	init_MUTEX(&journal->j_checkpoint_sem);	init_MUTEX(&journal->j_sem);	journal->j_commit_interval = (HZ * 5);	/* The journal is marked for error until we succeed with recovery! */	journal->j_flags = JFS_ABORT;	/* Set up a default-sized revoke table for the new mount. */	err = journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);	if (err) {		kfree(journal);		goto fail;	}	return journal;fail:	MOD_DEC_USE_COUNT;	return NULL;}/* journal_init_dev and journal_init_inode: * * Create a journal structure assigned some fixed set of disk blocks to * the journal.  We don't actually touch those disk blocks yet, but we * need to set up all of the mapping information to tell the journaling * system where the journal blocks are. * * journal_init_dev creates a journal which maps a fixed contiguous * range of blocks on an arbitrary block device. * * 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_dev(kdev_t dev, kdev_t fs_dev,			int start, int len, int blocksize){	journal_t *journal = journal_init_common();	struct buffer_head *bh;	if (!journal)		return NULL;	journal->j_dev = dev;	journal->j_fs_dev = fs_dev;	journal->j_blk_offset = start;	journal->j_maxlen = len;	journal->j_blocksize = blocksize;	bh = getblk(journal->j_dev, start, journal->j_blocksize);	J_ASSERT(bh != NULL);	journal->j_sb_buffer = bh;	journal->j_superblock = (journal_superblock_t *)bh->b_data;	return journal;}journal_t * journal_init_inode (struct inode *inode){	struct buffer_head *bh;	journal_t *journal = journal_init_common();	int err;	unsigned long blocknr;	if (!journal)		return NULL;	journal->j_dev = inode->i_dev;	journal->j_fs_dev = inode->i_dev;	journal->j_inode = inode;	jbd_debug(1,		  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",		  journal, bdevname(inode->i_dev), inode->i_ino, 		  (long long) inode->i_size,		  inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);	journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;	journal->j_blocksize = inode->i_sb->s_blocksize;	err = journal_bmap(journal, 0, &blocknr);	/* If that failed, give up */	if (err) {		printk(KERN_ERR __FUNCTION__ ": Cannnot locate journal "		       "superblock\n");		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;}/*  * If the journal init or create aborts, we need to mark the journal * superblock as being NULL to prevent the journal destroy from writing * back a bogus superblock.  */static void journal_fail_superblock (journal_t *journal){	struct buffer_head *bh = journal->j_sb_buffer;	brelse(bh);	journal->j_sb_buffer = NULL;}/* * Given a journal_t structure, initialise the various fields for * startup of a new journaling session.  We use this both when creating * a journal, and after recovering an old journal to reset it for * subsequent use. */static int journal_reset (journal_t *journal){	journal_superblock_t *sb = journal->j_superblock;	unsigned int first, last;	first = ntohl(sb->s_first);	last = ntohl(sb->s_maxlen);	journal->j_first = first;	journal->j_last = last;	journal->j_head = first;	journal->j_tail = first;	journal->j_free = last - first;	journal->j_tail_sequence = journal->j_transaction_sequence;	journal->j_commit_sequence = journal->j_transaction_sequence - 1;	journal->j_commit_request = journal->j_commit_sequence;	journal->j_max_transaction_buffers = journal->j_maxlen / 4;	/* Add the dynamic fields and write it to disk. */	journal_update_superblock(journal, 1);	lock_journal(journal);	journal_start_thread(journal);	unlock_journal(journal);	return 0;}/* * Given a journal_t structure which tells us which disk blocks we can * use, create a new journal superblock and initialise all of the * journal fields from scratch.  */int journal_create (journal_t *journal){	unsigned long blocknr;	struct buffer_head *bh;	journal_superblock_t *sb;	int i, err;	if (journal->j_maxlen < JFS_MIN_JOURNAL_BLOCKS) {		printk (KERN_ERR "Journal length (%d blocks) too short.\n",			journal->j_maxlen);		journal_fail_superblock(journal);		return -EINVAL;	}	if (journal->j_inode == NULL) {		/*		 * We don't know what block to start at!		 */		printk(KERN_EMERG __FUNCTION__			": creation of journal on external device!\n");		BUG();	}	/* Zero out the entire journal on disk.  We cannot afford to	   have any blocks on disk beginning with JFS_MAGIC_NUMBER. */	jbd_debug(1, "JBD: Zeroing out journal blocks...\n");	for (i = 0; i < journal->j_maxlen; i++) {		err = journal_bmap(journal, i, &blocknr);		if (err)			return err;		bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);		wait_on_buffer(bh);		memset (bh->b_data, 0, journal->j_blocksize);		BUFFER_TRACE(bh, "marking dirty");		mark_buffer_dirty(bh);		BUFFER_TRACE(bh, "marking uptodate");		mark_buffer_uptodate(bh, 1);		__brelse(bh);	}	sync_dev(journal->j_dev);	jbd_debug(1, "JBD: journal cleared.\n");	/* OK, fill in the initial static fields in the new superblock */	sb = journal->j_superblock;	sb->s_header.h_magic	 = htonl(JFS_MAGIC_NUMBER);	sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);	sb->s_blocksize	= htonl(journal->j_blocksize);	sb->s_maxlen	= htonl(journal->j_maxlen);	sb->s_first	= htonl(1);	journal->j_transaction_sequence = 1;	journal->j_flags &= ~JFS_ABORT;	journal->j_format_version = 2;	return journal_reset(journal);}/* * Update a journal's dynamic superblock fields and write it to disk, * optionally waiting for the IO to complete.*/void journal_update_superblock(journal_t *journal, int wait){	journal_superblock_t *sb = journal->j_superblock;	struct buffer_head *bh = journal->j_sb_buffer;	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);	sb->s_sequence = htonl(journal->j_tail_sequence);	sb->s_start    = htonl(journal->j_tail);	sb->s_errno    = htonl(journal->j_errno);	BUFFER_TRACE(bh, "marking dirty");	mark_buffer_dirty(bh);	ll_rw_block(WRITE, 1, &bh);

⌨️ 快捷键说明

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