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

📄 super.c

📁 嵌入式系统设计与实例开发源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	loff_t res = EXT3_NDIR_BLOCKS;	res += 1LL << (bits-2);	res += 1LL << (2*(bits-2));	res += 1LL << (3*(bits-2));	res <<= bits;	if (res > (512LL << 32) - (1 << bits))		res = (512LL << 32) - (1 << bits);	return res;}struct super_block * ext3_read_super (struct super_block * sb, void * data,				      int silent){	struct buffer_head * bh;	struct ext3_super_block *es = 0;	struct ext3_sb_info *sbi = EXT3_SB(sb);	unsigned long sb_block = 1;	unsigned long logic_sb_block = 1;	unsigned long offset = 0;	unsigned long journal_inum = 0;	kdev_t dev = sb->s_dev;	int blocksize;	int hblock;	int db_count;	int i;	int needs_recovery;#ifdef CONFIG_JBD_DEBUG	ext3_ro_after = 0;#endif	/*	 * See what the current blocksize for the device is, and	 * use that as the blocksize.  Otherwise (or if the blocksize	 * is smaller than the default) use the default.	 * This is important for devices that have a hardware	 * sectorsize that is larger than the default.	 */	blocksize = EXT3_MIN_BLOCK_SIZE;	hblock = get_hardsect_size(dev);	if (blocksize < hblock)		blocksize = hblock;	sbi->s_mount_opt = 0;	sbi->s_resuid = EXT3_DEF_RESUID;	sbi->s_resgid = EXT3_DEF_RESGID;	if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {		sb->s_dev = 0;		goto out_fail;	}	sb->s_blocksize = blocksize;	set_blocksize (dev, blocksize);	/*	 * The ext3 superblock will not be buffer aligned for other than 1kB	 * block sizes.  We need to calculate the offset from buffer start.	 */	if (blocksize != EXT3_MIN_BLOCK_SIZE) {		logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;		offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;	}	if (!(bh = sb_bread(sb, logic_sb_block))) {		printk (KERN_ERR "EXT3-fs: unable to read superblock\n");		goto out_fail;	}	/*	 * Note: s_es must be initialized as soon as possible because	 *       some ext3 macro-instructions depend on its value	 */	es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);	sbi->s_es = es;	sb->s_magic = le16_to_cpu(es->s_magic);	if (sb->s_magic != EXT3_SUPER_MAGIC) {		if (!silent)			printk(KERN_ERR 			       "VFS: Can't find ext3 filesystem on dev %s.\n",			       bdevname(dev));		goto failed_mount;	}	if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&	    (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||	     EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||	     EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))		printk(KERN_WARNING 		       "EXT3-fs warning: feature flags set on rev 0 fs, "		       "running e2fsck is recommended\n");	/*	 * Check feature flags regardless of the revision level, since we	 * previously didn't change the revision level when setting the flags,	 * so there is a chance incompat flags are set on a rev 0 filesystem.	 */	if ((i = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {		printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "		       "unsupported optional features (%x).\n",		       bdevname(dev), i);		goto failed_mount;	}	if (!(sb->s_flags & MS_RDONLY) &&	    (i = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){		printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "		       "unsupported optional features (%x).\n",		       bdevname(dev), i);		goto failed_mount;	}	sb->s_blocksize_bits = le32_to_cpu(es->s_log_block_size) + 10;	sb->s_blocksize = 1 << sb->s_blocksize_bits;	if (sb->s_blocksize < EXT3_MIN_BLOCK_SIZE ||	    sb->s_blocksize > EXT3_MAX_BLOCK_SIZE) {		printk(KERN_ERR 		       "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",		       blocksize, bdevname(dev));		goto failed_mount;	}	sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits);	if (sb->s_blocksize != blocksize) {		blocksize = sb->s_blocksize;		/*		 * Make sure the blocksize for the filesystem is larger		 * than the hardware sectorsize for the machine.		 */		if (sb->s_blocksize < hblock) {			printk(KERN_ERR "EXT3-fs: blocksize %d too small for "			       "device blocksize %d.\n", blocksize, hblock);			goto failed_mount;		}		brelse (bh);		set_blocksize (dev, sb->s_blocksize);		logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;		offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;		bh = sb_bread(sb, logic_sb_block);		if (!bh) {			printk(KERN_ERR 			       "EXT3-fs: Can't read superblock on 2nd try.\n");			return NULL;		}		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);		sbi->s_es = es;		if (es->s_magic != le16_to_cpu(EXT3_SUPER_MAGIC)) {			printk (KERN_ERR 				"EXT3-fs: Magic mismatch, very weird !\n");			goto failed_mount;		}	}	if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV) {		sbi->s_inode_size = EXT3_GOOD_OLD_INODE_SIZE;		sbi->s_first_ino = EXT3_GOOD_OLD_FIRST_INO;	} else {		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);		if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {			printk (KERN_ERR				"EXT3-fs: unsupported inode size: %d\n",				sbi->s_inode_size);			goto failed_mount;		}	}	sbi->s_frag_size = EXT3_MIN_FRAG_SIZE <<				   le32_to_cpu(es->s_log_frag_size);	if (blocksize != sbi->s_frag_size) {		printk(KERN_ERR		       "EXT3-fs: fragsize %lu != blocksize %u (unsupported)\n",		       sbi->s_frag_size, blocksize);		goto failed_mount;	}	sbi->s_frags_per_block = 1;	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);	sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);	sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);	sbi->s_itb_per_group = sbi->s_inodes_per_group /sbi->s_inodes_per_block;	sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);	sbi->s_sbh = bh;	if (sbi->s_resuid == EXT3_DEF_RESUID)		sbi->s_resuid = le16_to_cpu(es->s_def_resuid);	if (sbi->s_resgid == EXT3_DEF_RESGID)		sbi->s_resgid = le16_to_cpu(es->s_def_resgid);	sbi->s_mount_state = le16_to_cpu(es->s_state);	sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));	sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));	if (sbi->s_blocks_per_group > blocksize * 8) {		printk (KERN_ERR			"EXT3-fs: #blocks per group too big: %lu\n",			sbi->s_blocks_per_group);		goto failed_mount;	}	if (sbi->s_frags_per_group > blocksize * 8) {		printk (KERN_ERR			"EXT3-fs: #fragments per group too big: %lu\n",			sbi->s_frags_per_group);		goto failed_mount;	}	if (sbi->s_inodes_per_group > blocksize * 8) {		printk (KERN_ERR			"EXT3-fs: #inodes per group too big: %lu\n",			sbi->s_inodes_per_group);		goto failed_mount;	}	sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -			       le32_to_cpu(es->s_first_data_block) +			       EXT3_BLOCKS_PER_GROUP(sb) - 1) /			      EXT3_BLOCKS_PER_GROUP(sb);	db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /		   EXT3_DESC_PER_BLOCK(sb);	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),				    GFP_KERNEL);	if (sbi->s_group_desc == NULL) {		printk (KERN_ERR "EXT3-fs: not enough memory\n");		goto failed_mount;	}	for (i = 0; i < db_count; i++) {		sbi->s_group_desc[i] = sb_bread(sb, logic_sb_block + i + 1);		if (!sbi->s_group_desc[i]) {			printk (KERN_ERR "EXT3-fs: "				"can't read group descriptor %d\n", i);			db_count = i;			goto failed_mount2;		}	}	if (!ext3_check_descriptors (sb)) {		printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");		goto failed_mount2;	}	for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++) {		sbi->s_inode_bitmap_number[i] = 0;		sbi->s_inode_bitmap[i] = NULL;		sbi->s_block_bitmap_number[i] = 0;		sbi->s_block_bitmap[i] = NULL;	}	sbi->s_loaded_inode_bitmaps = 0;	sbi->s_loaded_block_bitmaps = 0;	sbi->s_gdb_count = db_count;	get_random_bytes(&sbi->s_next_generation, sizeof(u32));	/*	 * set up enough so that it can read an inode	 */	sb->s_op = &ext3_sops;	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */	sb->s_root = 0;	needs_recovery = (es->s_last_orphan != 0 ||			  EXT3_HAS_INCOMPAT_FEATURE(sb,				    EXT3_FEATURE_INCOMPAT_RECOVER));	/*	 * The first inode we look at is the journal inode.  Don't try	 * root first: it may be modified in the journal!	 */	if (!test_opt(sb, NOLOAD) &&	    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {		if (ext3_load_journal(sb, es))			goto failed_mount2;	} else if (journal_inum) {		if (ext3_create_journal(sb, es, journal_inum))			goto failed_mount2;	} else {		if (!silent)			printk (KERN_ERR				"ext3: No journal on filesystem on %s\n",				bdevname(dev));		goto failed_mount2;	}	/* We have now updated the journal if required, so we can	 * validate the data journaling mode. */	switch (test_opt(sb, DATA_FLAGS)) {	case 0:		/* No mode set, assume a default based on the journal                   capabilities: ORDERED_DATA if the journal can                   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_mount3;		}	default:		break;	}	/*	 * The journal_load will have done any necessary log recovery,	 * so we can safely mount the rest of the filesystem now.	 */	sb->s_root = d_alloc_root(iget(sb, EXT3_ROOT_INO));	if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) ||	    !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) {		if (sb->s_root) {			dput(sb->s_root);			sb->s_root = NULL;			printk(KERN_ERR			       "EXT3-fs: corrupt root inode, run e2fsck\n");		} else			printk(KERN_ERR "EXT3-fs: get root inode failed\n");		goto failed_mount3;	}	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;	unlock_super(sb);	/* akpm: sigh */	ext3_orphan_cleanup(sb, es);	lock_super(sb);	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");	return sb;failed_mount3:	journal_destroy(sbi->s_journal);failed_mount2:	for (i = 0; i < db_count; i++)		brelse(sbi->s_group_desc[i]);	kfree(sbi->s_group_desc);failed_mount:	ext3_blkdev_remove(sbi);	brelse(bh);out_fail:	return NULL;}static journal_t *ext3_get_journal(struct super_block *sb, 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 journal;}static journal_t *ext3_get_dev_journal(struct super_block *sb,				       int dev){	struct buffer_head * bh;	journal_t *journal;	int start;	int len;	int hblock, blocksize;	unsigned long sb_block;	unsigned long offset;	kdev_t journal_dev = to_kdev_t(dev);	struct ext3_super_block * es;	struct block_device *bdev;	bdev = ext3_blkdev_get(journal_dev);	if (bdev == NULL)		return NULL;	blocksize = sb->s_blocksize;	hblock = get_hardsect_size(journal_dev);	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(dev, blocksize);	if (!(bh = bread(dev, 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);

⌨️ 快捷键说明

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