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

📄 journal.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static int journal_get_superblock(journal_t *journal){	struct buffer_head *bh;	journal_superblock_t *sb;	int err = -EIO;	bh = journal->j_sb_buffer;	J_ASSERT(bh != NULL);	if (!buffer_uptodate(bh)) {		ll_rw_block(READ, 1, &bh);		wait_on_buffer(bh);		if (!buffer_uptodate(bh)) {			printk (KERN_ERR				"JBD: IO error reading journal superblock\n");			goto out;		}	}	sb = journal->j_superblock;	err = -EINVAL;	if (sb->s_header.h_magic != cpu_to_be32(JFS_MAGIC_NUMBER) ||	    sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {		printk(KERN_WARNING "JBD: no valid journal superblock found\n");		goto out;	}	switch(be32_to_cpu(sb->s_header.h_blocktype)) {	case JFS_SUPERBLOCK_V1:		journal->j_format_version = 1;		break;	case JFS_SUPERBLOCK_V2:		journal->j_format_version = 2;		break;	default:		printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");		goto out;	}	if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)		journal->j_maxlen = be32_to_cpu(sb->s_maxlen);	else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {		printk (KERN_WARNING "JBD: journal file too short\n");		goto out;	}	return 0;out:	journal_fail_superblock(journal);	return err;}/* * Load the on-disk journal superblock and read the key fields into the * journal_t. */static int load_superblock(journal_t *journal){	int err;	journal_superblock_t *sb;	err = journal_get_superblock(journal);	if (err)		return err;	sb = journal->j_superblock;	journal->j_tail_sequence = be32_to_cpu(sb->s_sequence);	journal->j_tail = be32_to_cpu(sb->s_start);	journal->j_first = be32_to_cpu(sb->s_first);	journal->j_last = be32_to_cpu(sb->s_maxlen);	journal->j_errno = be32_to_cpu(sb->s_errno);	return 0;}/** * int journal_load() - Read journal from disk. * @journal: Journal to act on. * * Given a journal_t structure which tells us which disk blocks contain * a journal, read the journal from disk to initialise the in-memory * structures. */int journal_load(journal_t *journal){	int err;	journal_superblock_t *sb;	err = load_superblock(journal);	if (err)		return err;	sb = journal->j_superblock;	/* If this is a V2 superblock, then we have to check the	 * features flags on it. */	if (journal->j_format_version >= 2) {		if ((sb->s_feature_ro_compat &		     ~cpu_to_be32(JFS_KNOWN_ROCOMPAT_FEATURES)) ||		    (sb->s_feature_incompat &		     ~cpu_to_be32(JFS_KNOWN_INCOMPAT_FEATURES))) {			printk (KERN_WARNING				"JBD: Unrecognised features on journal\n");			return -EINVAL;		}	}	/* Let the recovery code check whether it needs to recover any	 * data from the journal. */	if (journal_recover(journal))		goto recovery_error;	/* OK, we've finished with the dynamic journal bits:	 * reinitialise the dynamic contents of the superblock in memory	 * and reset them on disk. */	if (journal_reset(journal))		goto recovery_error;	journal->j_flags &= ~JFS_ABORT;	journal->j_flags |= JFS_LOADED;	return 0;recovery_error:	printk (KERN_WARNING "JBD: recovery failed\n");	return -EIO;}/** * 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){	/* 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... */	spin_lock(&journal->j_list_lock);	while (journal->j_checkpoint_transactions != NULL) {		spin_unlock(&journal->j_list_lock);		log_do_checkpoint(journal);		spin_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);	spin_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);	}	if (journal->j_inode)		iput(journal->j_inode);	if (journal->j_revoke)		journal_destroy_revoke(journal);	kfree(journal->j_wbuf);	kfree(journal);}/** *int journal_check_used_features () - Check if features specified are used. * @journal: Journal to check. * @compat: bitmask of compatible features * @ro: bitmask of features that force read-only mount * @incompat: bitmask of incompatible features * * Check whether the journal uses all of a given set of * features.  Return true (non-zero) if it does. **/int journal_check_used_features (journal_t *journal, unsigned long compat,				 unsigned long ro, unsigned long incompat){	journal_superblock_t *sb;	if (!compat && !ro && !incompat)		return 1;	if (journal->j_format_version == 1)		return 0;	sb = journal->j_superblock;	if (((be32_to_cpu(sb->s_feature_compat) & compat) == compat) &&	    ((be32_to_cpu(sb->s_feature_ro_compat) & ro) == ro) &&	    ((be32_to_cpu(sb->s_feature_incompat) & incompat) == incompat))		return 1;	return 0;}/** * int journal_check_available_features() - Check feature set in journalling layer * @journal: Journal to check. * @compat: bitmask of compatible features * @ro: bitmask of features that force read-only mount * @incompat: bitmask of incompatible features * * Check whether the journaling code supports the use of * all of a given set of features on this journal.  Return true * (non-zero) if it can. */int journal_check_available_features (journal_t *journal, unsigned long compat,				      unsigned long ro, unsigned long incompat){	journal_superblock_t *sb;	if (!compat && !ro && !incompat)		return 1;	sb = journal->j_superblock;	/* We can support any known requested features iff the	 * superblock is in version 2.  Otherwise we fail to support any	 * extended sb features. */	if (journal->j_format_version != 2)		return 0;	if ((compat   & JFS_KNOWN_COMPAT_FEATURES) == compat &&	    (ro       & JFS_KNOWN_ROCOMPAT_FEATURES) == ro &&	    (incompat & JFS_KNOWN_INCOMPAT_FEATURES) == incompat)		return 1;	return 0;}/** * int journal_set_features () - Mark a given journal feature in the superblock * @journal: Journal to act on. * @compat: bitmask of compatible features * @ro: bitmask of features that force read-only mount * @incompat: bitmask of incompatible features * * Mark a given journal feature as present on the * superblock.  Returns true if the requested features could be set. * */int journal_set_features (journal_t *journal, unsigned long compat,			  unsigned long ro, unsigned long incompat){	journal_superblock_t *sb;	if (journal_check_used_features(journal, compat, ro, incompat))		return 1;	if (!journal_check_available_features(journal, compat, ro, incompat))		return 0;	jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",		  compat, ro, incompat);	sb = journal->j_superblock;	sb->s_feature_compat    |= cpu_to_be32(compat);	sb->s_feature_ro_compat |= cpu_to_be32(ro);	sb->s_feature_incompat  |= cpu_to_be32(incompat);	return 1;}/** * int journal_update_format () - Update on-disk journal structure. * @journal: Journal to act on. * * Given an initialised but unloaded journal struct, poke about in the * on-disk structure to update it to the most recent supported version. */int journal_update_format (journal_t *journal){	journal_superblock_t *sb;	int err;	err = journal_get_superblock(journal);	if (err)		return err;	sb = journal->j_superblock;	switch (be32_to_cpu(sb->s_header.h_blocktype)) {	case JFS_SUPERBLOCK_V2:		return 0;	case JFS_SUPERBLOCK_V1:		return journal_convert_superblock_v1(journal, sb);	default:		break;	}	return -EINVAL;}static int journal_convert_superblock_v1(journal_t *journal,					 journal_superblock_t *sb){	int offset, blocksize;	struct buffer_head *bh;	printk(KERN_WARNING		"JBD: Converting superblock from version 1 to 2.\n");	/* Pre-initialise new fields to zero */	offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);	blocksize = be32_to_cpu(sb->s_blocksize);	memset(&sb->s_feature_compat, 0, blocksize-offset);	sb->s_nr_users = cpu_to_be32(1);	sb->s_header.h_blocktype = cpu_to_be32(JFS_SUPERBLOCK_V2);	journal->j_format_version = 2;	bh = journal->j_sb_buffer;	BUFFER_TRACE(bh, "marking dirty");	mark_buffer_dirty(bh);	sync_dirty_buffer(bh);	return 0;}/** * int journal_flush () - Flush journal * @journal: Journal to act on. * * Flush all data for a given journal to disk and empty the journal. * Filesystems can use this when remounting readonly to ensure that * recovery does not need to happen on remount. */int journal_flush(journal_t *journal){	int err = 0;	transaction_t *transaction = NULL;	unsigned long old_tail;	spin_lock(&journal->j_state_lock);	/* Force everything buffered to the log... */	if (journal->j_running_transaction) {		transaction = journal->j_running_transaction;		__log_start_commit(journal, transaction->t_tid);	} else if (journal->j_committing_transaction)		transaction = journal->j_committing_transaction;	/* Wait for the log commit to complete... */	if (transaction) {		tid_t tid = transaction->t_tid;		spin_unlock(&journal->j_state_lock);		log_wait_commit(journal, tid);	} else {		spin_unlock(&journal->j_state_lock);	}	/* ...and flush everything in the log out to disk. */	spin_lock(&journal->j_list_lock);	while (!err && journal->j_checkpoint_transactions != NULL) {		spin_unlock(&journal->j_list_lock);		err = log_do_checkpoint(journal);		spin_lock(&journal->j_list_lock);	}	spin_unlock(&journal->j_list_lock);	cleanup_journal_tail(journal);	/* Finally, mark the journal as really needing no recovery.	 * This sets s_start==0 in the underlying superblock, which is	 * the magic code for a fully-recovered superblock.  Any future	 * commits of data to the journal will restore the current	 * s_start value. */	spin_lock(&journal->j_state_lock);	old_tail = journal->j_tail;	journal->j_tail = 0;	spin_unlock(&journal->j_state_lock);	journal_update_superblock(journal, 1);	spin_lock(&journal->j_state_lock);	journal->j_tail = old_tail;	J_ASSERT(!journal->j_running_transaction);	J_ASSERT(!journal->j_committing_transaction);	J_ASSERT(!journal->j_checkpoint_transactions);	J_ASSERT(journal->j_head == journal->j_tail);	J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);	spin_unlock(&journal->j_state_lock);	return err;}/** * int journal_wipe() - Wipe journal contents * @journal: Journal to act on. * @write: flag (see below) * * Wipe out all of the contents of a journal, safely.  This will produce * a warning if the journal contains any valid recovery information. * Must be called between journal_init_*() and journal_load(). * * If 'write' is non-zero, then we wipe out the journal on disk; otherwise * we merely suppress recovery. */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;}/* * journal_dev_name: format a character string to describe on what * device this journal is present. */static const char *journal_dev_name(journal_t *journal, char *buffer){	struct block_device *bdev;	if (journal->j_inode)		bdev = journal->j_inode->i_sb->s_bdev;	else		bdev = journal->j_dev;	return bdevname(bdev, buffer);}/* * Journal abort has very specific semantics, which we describe * for journal abort. * * Two internal function, which provide abort to te jbd layer * itself are here. *//* * Quick version for internal journal use (doesn't lock the journal). * Aborts hard --- we mark the abort as occurred, but do _nothing_ else, * and don't attempt to make any other journal updates. */void __journal_abort_hard(journal_t *journal){	transaction_t *transaction;	char b[BDEVNAME_SIZE];	if (journal->j_flags & JFS_ABORT)		return;	printk(KERN_ERR "Aborting journal on device %s.\n",		journal_dev_name(journal, b));	spin_lock(&journal->j_state_lock);	journal->j_flags |= JFS_ABORT;	transaction = journal->j_running_transaction;	if (transaction)		__log_start_commit(journal, transaction->t_tid);	spin_unlock(&journal->j_state_lock);

⌨️ 快捷键说明

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