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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                   cope, else JOURNAL_DATA */		if (journal_check_available_features		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))			set_opt(sbi->s_mount_opt, ORDERED_DATA);		else			set_opt(sbi->s_mount_opt, JOURNAL_DATA);		break;	case EXT3_MOUNT_ORDERED_DATA:	case EXT3_MOUNT_WRITEBACK_DATA:		if (!journal_check_available_features		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {			printk(KERN_ERR "EXT3-fs: Journal does not support "			       "requested data journaling mode\n");			goto failed_mount4;		}	default:		break;	}	if (test_opt(sb, NOBH)) {		if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) {			printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - "				"its supported only with writeback mode\n");			clear_opt(sbi->s_mount_opt, NOBH);		}	}	/*	 * The journal_load will have done any necessary log recovery,	 * so we can safely mount the rest of the filesystem now.	 */	root = iget(sb, EXT3_ROOT_INO);	sb->s_root = d_alloc_root(root);	if (!sb->s_root) {		printk(KERN_ERR "EXT3-fs: get root inode failed\n");		iput(root);		goto failed_mount4;	}	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {		dput(sb->s_root);		sb->s_root = NULL;		printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");		goto failed_mount4;	}	ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);	/*	 * akpm: core read_super() calls in here with the superblock locked.	 * That deadlocks, because orphan cleanup needs to lock the superblock	 * in numerous places.  Here we just pop the lock - it's relatively	 * harmless, because we are now ready to accept write_super() requests,	 * and aviro says that's the only reason for hanging onto the	 * superblock lock.	 */	EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;	ext3_orphan_cleanup(sb, es);	EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;	if (needs_recovery)		printk (KERN_INFO "EXT3-fs: recovery complete.\n");	ext3_mark_recovery_complete(sb, es);	printk (KERN_INFO "EXT3-fs: mounted filesystem with %s data mode.\n",		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":		"writeback");	lock_kernel();	return 0;cantfind_ext3:	if (!silent)		printk(KERN_ERR "VFS: Can't find ext3 filesystem on dev %s.\n",		       sb->s_id);	goto failed_mount;failed_mount4:	journal_destroy(sbi->s_journal);failed_mount3:	percpu_counter_destroy(&sbi->s_freeblocks_counter);	percpu_counter_destroy(&sbi->s_freeinodes_counter);	percpu_counter_destroy(&sbi->s_dirs_counter);failed_mount2:	for (i = 0; i < db_count; i++)		brelse(sbi->s_group_desc[i]);	kfree(sbi->s_group_desc);failed_mount:#ifdef CONFIG_QUOTA	for (i = 0; i < MAXQUOTAS; i++)		kfree(sbi->s_qf_names[i]);#endif	ext3_blkdev_remove(sbi);	brelse(bh);out_fail:	sb->s_fs_info = NULL;	kfree(sbi);	lock_kernel();	return -EINVAL;}/* * Setup any per-fs journal parameters now.  We'll do this both on * initial mount, once the journal has been initialised but before we've * done any recovery; and again on any subsequent remount. */static void ext3_init_journal_params(struct super_block *sb, journal_t *journal){	struct ext3_sb_info *sbi = EXT3_SB(sb);	if (sbi->s_commit_interval)		journal->j_commit_interval = sbi->s_commit_interval;	/* We could also set up an ext3-specific default for the commit	 * interval here, but for now we'll just fall back to the jbd	 * default. */	spin_lock(&journal->j_state_lock);	if (test_opt(sb, BARRIER))		journal->j_flags |= JFS_BARRIER;	else		journal->j_flags &= ~JFS_BARRIER;	spin_unlock(&journal->j_state_lock);}static journal_t *ext3_get_journal(struct super_block *sb,				   unsigned int journal_inum){	struct inode *journal_inode;	journal_t *journal;	/* First, test for the existence of a valid inode on disk.  Bad	 * things happen if we iget() an unused inode, as the subsequent	 * iput() will try to delete it. */	journal_inode = iget(sb, journal_inum);	if (!journal_inode) {		printk(KERN_ERR "EXT3-fs: no journal found.\n");		return NULL;	}	if (!journal_inode->i_nlink) {		make_bad_inode(journal_inode);		iput(journal_inode);		printk(KERN_ERR "EXT3-fs: journal inode is deleted.\n");		return NULL;	}	jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",		  journal_inode, journal_inode->i_size);	if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {		printk(KERN_ERR "EXT3-fs: invalid journal inode.\n");		iput(journal_inode);		return NULL;	}	journal = journal_init_inode(journal_inode);	if (!journal) {		printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");		iput(journal_inode);		return NULL;	}	journal->j_private = sb;	ext3_init_journal_params(sb, journal);	return journal;}static journal_t *ext3_get_dev_journal(struct super_block *sb,				       dev_t j_dev){	struct buffer_head * bh;	journal_t *journal;	ext3_fsblk_t start;	ext3_fsblk_t len;	int hblock, blocksize;	ext3_fsblk_t sb_block;	unsigned long offset;	struct ext3_super_block * es;	struct block_device *bdev;	bdev = ext3_blkdev_get(j_dev);	if (bdev == NULL)		return NULL;	if (bd_claim(bdev, sb)) {		printk(KERN_ERR		        "EXT3: failed to claim external journal device.\n");		blkdev_put(bdev);		return NULL;	}	blocksize = sb->s_blocksize;	hblock = bdev_hardsect_size(bdev);	if (blocksize < hblock) {		printk(KERN_ERR			"EXT3-fs: blocksize too small for journal device.\n");		goto out_bdev;	}	sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;	offset = EXT3_MIN_BLOCK_SIZE % blocksize;	set_blocksize(bdev, blocksize);	if (!(bh = __bread(bdev, sb_block, blocksize))) {		printk(KERN_ERR "EXT3-fs: couldn't read superblock of "		       "external journal\n");		goto out_bdev;	}	es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);	if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||	    !(le32_to_cpu(es->s_feature_incompat) &	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {		printk(KERN_ERR "EXT3-fs: external journal has "					"bad superblock\n");		brelse(bh);		goto out_bdev;	}	if (memcmp(EXT3_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {		printk(KERN_ERR "EXT3-fs: journal UUID does not match\n");		brelse(bh);		goto out_bdev;	}	len = le32_to_cpu(es->s_blocks_count);	start = sb_block + 1;	brelse(bh);	/* we're done with the superblock */	journal = journal_init_dev(bdev, sb->s_bdev,					start, len, blocksize);	if (!journal) {		printk(KERN_ERR "EXT3-fs: failed to create device journal\n");		goto out_bdev;	}	journal->j_private = sb;	ll_rw_block(READ, 1, &journal->j_sb_buffer);	wait_on_buffer(journal->j_sb_buffer);	if (!buffer_uptodate(journal->j_sb_buffer)) {		printk(KERN_ERR "EXT3-fs: I/O error on journal device\n");		goto out_journal;	}	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {		printk(KERN_ERR "EXT3-fs: External journal has more than one "					"user (unsupported) - %d\n",			be32_to_cpu(journal->j_superblock->s_nr_users));		goto out_journal;	}	EXT3_SB(sb)->journal_bdev = bdev;	ext3_init_journal_params(sb, journal);	return journal;out_journal:	journal_destroy(journal);out_bdev:	ext3_blkdev_put(bdev);	return NULL;}static int ext3_load_journal(struct super_block *sb,			     struct ext3_super_block *es,			     unsigned long journal_devnum){	journal_t *journal;	unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);	dev_t journal_dev;	int err = 0;	int really_read_only;	if (journal_devnum &&	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {		printk(KERN_INFO "EXT3-fs: external journal device major/minor "			"numbers have changed\n");		journal_dev = new_decode_dev(journal_devnum);	} else		journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));	really_read_only = bdev_read_only(sb->s_bdev);	/*	 * Are we loading a blank journal or performing recovery after a	 * crash?  For recovery, we need to check in advance whether we	 * can get read-write access to the device.	 */	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) {		if (sb->s_flags & MS_RDONLY) {			printk(KERN_INFO "EXT3-fs: INFO: recovery "					"required on readonly filesystem.\n");			if (really_read_only) {				printk(KERN_ERR "EXT3-fs: write access "					"unavailable, cannot proceed.\n");				return -EROFS;			}			printk (KERN_INFO "EXT3-fs: write access will "					"be enabled during recovery.\n");		}	}	if (journal_inum && journal_dev) {		printk(KERN_ERR "EXT3-fs: filesystem has both journal "		       "and inode journals!\n");		return -EINVAL;	}	if (journal_inum) {		if (!(journal = ext3_get_journal(sb, journal_inum)))			return -EINVAL;	} else {		if (!(journal = ext3_get_dev_journal(sb, journal_dev)))			return -EINVAL;	}	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {		err = journal_update_format(journal);		if (err)  {			printk(KERN_ERR "EXT3-fs: error updating journal.\n");			journal_destroy(journal);			return err;		}	}	if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER))		err = journal_wipe(journal, !really_read_only);	if (!err)		err = journal_load(journal);	if (err) {		printk(KERN_ERR "EXT3-fs: error loading journal.\n");		journal_destroy(journal);		return err;	}	EXT3_SB(sb)->s_journal = journal;	ext3_clear_journal_err(sb, es);	if (journal_devnum &&	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {		es->s_journal_dev = cpu_to_le32(journal_devnum);		sb->s_dirt = 1;		/* Make sure we flush the recovery flag to disk. */		ext3_commit_super(sb, es, 1);	}	return 0;}static int ext3_create_journal(struct super_block * sb,			       struct ext3_super_block * es,			       unsigned int journal_inum){	journal_t *journal;	int err;	if (sb->s_flags & MS_RDONLY) {		printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "				"create journal.\n");		return -EROFS;	}	journal = ext3_get_journal(sb, journal_inum);	if (!journal)		return -EINVAL;	printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",	       journal_inum);	err = journal_create(journal);	if (err) {		printk(KERN_ERR "EXT3-fs: error creating journal.\n");		journal_destroy(journal);		return -EIO;	}	EXT3_SB(sb)->s_journal = journal;	ext3_update_dynamic_rev(sb);	EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);	EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL);	es->s_journal_inum = cpu_to_le32(journal_inum);	sb->s_dirt = 1;	/* Make sure we flush the recovery flag to disk. */	ext3_commit_super(sb, es, 1);	return 0;}static void ext3_commit_super (struct super_block * sb,			       struct ext3_super_block * es,			       int sync){	struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;	if (!sbh)		return;	es->s_wtime = cpu_to_le32(get_seconds());	es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));	es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));	BUFFER_TRACE(sbh, "marking dirty");	mark_buffer_dirty(sbh);	if (sync)		sync_dirty_buffer(sbh);}/* * Have we just finished recovery?  If so, and if we are mounting (or * remounting) the filesystem readonly, then we will end up with a * consistent fs on disk.  Record that fact. */static void ext3_mark_recovery_complete(struct super_block * sb,					struct ext3_super_block * es){	journal_t *journal = EXT3_SB(sb)->s_journal;	journal_lock_updates(journal);	journal_flush(journal);	lock_super(sb);	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&	    sb->s_flags & MS_RDONLY) {		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);		sb->s_dirt = 0;		ext3_commit_super(sb, es, 1);	}	unlock_super(sb);	journal_unlock_updates(journal);}/* * If we are mounting (or read-write remounting) a filesystem whose journal * has recorded an error from a previous lifetime, move that error to the * main filesystem now. */static void ext3_clear_journal_err(struct super_block * sb,				   struct ext3_super_block * es){	journal_t *journal;	int j_errno;	const char *errstr;	journal = EXT3_SB(sb)->s_journal;	/*	 * Now check for any error status which may have been recorded in the	 * journal by a prior ext3_error() or ext3_abort()	 */	j_errno = journal_errno(journal);	if (j_errno) {		char nbuf[16];		errstr = ext3_decode_error(sb, j_errno, nbuf);		ext3_warning(sb, __FUNCTION__, "Filesystem error recorded "			     "from previous mount: %s", errstr);		ext3_warning(sb, __FUNCTION__, "Marking fs in need of "			     "filesystem check.");		EXT3_SB(sb)->s_mount_state

⌨️ 快捷键说明

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