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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Called at mount-time, super-block is locked */static int ext4_check_descriptors (struct super_block * sb){	struct ext4_sb_info *sbi = EXT4_SB(sb);	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);	ext4_fsblk_t last_block;	ext4_fsblk_t block_bitmap;	ext4_fsblk_t inode_bitmap;	ext4_fsblk_t inode_table;	struct ext4_group_desc * gdp = NULL;	int desc_block = 0;	int flexbg_flag = 0;	int i;	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))		flexbg_flag = 1;	ext4_debug ("Checking group descriptors");	for (i = 0; i < sbi->s_groups_count; i++)	{		if (i == sbi->s_groups_count - 1 || flexbg_flag)			last_block = ext4_blocks_count(sbi->s_es) - 1;		else			last_block = first_block +				(EXT4_BLOCKS_PER_GROUP(sb) - 1);		if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)			gdp = (struct ext4_group_desc *)					sbi->s_group_desc[desc_block++]->b_data;		block_bitmap = ext4_block_bitmap(sb, gdp);		if (block_bitmap < first_block || block_bitmap > last_block)		{			ext4_error (sb, "ext4_check_descriptors",				    "Block bitmap for group %d"				    " not in group (block %llu)!",				    i, block_bitmap);			return 0;		}		inode_bitmap = ext4_inode_bitmap(sb, gdp);		if (inode_bitmap < first_block || inode_bitmap > last_block)		{			ext4_error (sb, "ext4_check_descriptors",				    "Inode bitmap for group %d"				    " not in group (block %llu)!",				    i, inode_bitmap);			return 0;		}		inode_table = ext4_inode_table(sb, gdp);		if (inode_table < first_block ||		    inode_table + sbi->s_itb_per_group - 1 > last_block)		{			ext4_error (sb, "ext4_check_descriptors",				    "Inode table for group %d"				    " not in group (block %llu)!",				    i, inode_table);			return 0;		}		if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {			ext4_error(sb, __FUNCTION__,				   "Checksum for group %d failed (%u!=%u)\n", i,				   le16_to_cpu(ext4_group_desc_csum(sbi, i,								    gdp)),				   le16_to_cpu(gdp->bg_checksum));			return 0;		}		if (!flexbg_flag)			first_block += EXT4_BLOCKS_PER_GROUP(sb);		gdp = (struct ext4_group_desc *)			((__u8 *)gdp + EXT4_DESC_SIZE(sb));	}	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext4_count_free_inodes(sb));	return 1;}/* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at * the superblock) which were deleted from all directories, but held open by * a process at the time of a crash.  We walk the list and try to delete these * inodes at recovery time (only with a read-write filesystem). * * In order to keep the orphan inode chain consistent during traversal (in * case of crash during recovery), we link each inode into the superblock * orphan list_head and handle it the same way as an inode deletion during * normal operation (which journals the operations for us). * * We only do an iget() and an iput() on each inode, which is very safe if we * accidentally point at an in-use or already deleted inode.  The worst that * can happen in this case is that we get a "bit already cleared" message from * ext4_free_inode().  The only reason we would point at a wrong inode is if * e2fsck was run on this filesystem, and it must have already done the orphan * inode cleanup for us, so we can safely abort without any further action. */static void ext4_orphan_cleanup (struct super_block * sb,				 struct ext4_super_block * es){	unsigned int s_flags = sb->s_flags;	int nr_orphans = 0, nr_truncates = 0;#ifdef CONFIG_QUOTA	int i;#endif	if (!es->s_last_orphan) {		jbd_debug(4, "no orphan inodes to clean up\n");		return;	}	if (bdev_read_only(sb->s_bdev)) {		printk(KERN_ERR "EXT4-fs: write access "			"unavailable, skipping orphan cleanup.\n");		return;	}	if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {		if (es->s_last_orphan)			jbd_debug(1, "Errors on filesystem, "				  "clearing orphan list.\n");		es->s_last_orphan = 0;		jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");		return;	}	if (s_flags & MS_RDONLY) {		printk(KERN_INFO "EXT4-fs: %s: orphan cleanup on readonly fs\n",		       sb->s_id);		sb->s_flags &= ~MS_RDONLY;	}#ifdef CONFIG_QUOTA	/* Needed for iput() to work correctly and not trash data */	sb->s_flags |= MS_ACTIVE;	/* Turn on quotas so that they are updated correctly */	for (i = 0; i < MAXQUOTAS; i++) {		if (EXT4_SB(sb)->s_qf_names[i]) {			int ret = ext4_quota_on_mount(sb, i);			if (ret < 0)				printk(KERN_ERR					"EXT4-fs: Cannot turn on journalled "					"quota: error %d\n", ret);		}	}#endif	while (es->s_last_orphan) {		struct inode *inode;		if (!(inode =		      ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {			es->s_last_orphan = 0;			break;		}		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);		DQUOT_INIT(inode);		if (inode->i_nlink) {			printk(KERN_DEBUG				"%s: truncating inode %lu to %Ld bytes\n",				__FUNCTION__, inode->i_ino, inode->i_size);			jbd_debug(2, "truncating inode %lu to %Ld bytes\n",				  inode->i_ino, inode->i_size);			ext4_truncate(inode);			nr_truncates++;		} else {			printk(KERN_DEBUG				"%s: deleting unreferenced inode %lu\n",				__FUNCTION__, inode->i_ino);			jbd_debug(2, "deleting unreferenced inode %lu\n",				  inode->i_ino);			nr_orphans++;		}		iput(inode);  /* The delete magic happens here! */	}#define PLURAL(x) (x), ((x)==1) ? "" : "s"	if (nr_orphans)		printk(KERN_INFO "EXT4-fs: %s: %d orphan inode%s deleted\n",		       sb->s_id, PLURAL(nr_orphans));	if (nr_truncates)		printk(KERN_INFO "EXT4-fs: %s: %d truncate%s cleaned up\n",		       sb->s_id, PLURAL(nr_truncates));#ifdef CONFIG_QUOTA	/* Turn quotas off */	for (i = 0; i < MAXQUOTAS; i++) {		if (sb_dqopt(sb)->files[i])			vfs_quota_off(sb, i);	}#endif	sb->s_flags = s_flags; /* Restore MS_RDONLY status */}/* * Maximal file size.  There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. * We need to be 1 filesystem block less than the 2^32 sector limit. */static loff_t ext4_max_size(int bits){	loff_t res = EXT4_NDIR_BLOCKS;	/* This constant is calculated to be the largest file size for a	 * dense, 4k-blocksize file such that the total number of	 * sectors in the file, including data and all indirect blocks,	 * does not exceed 2^32. */	const loff_t upper_limit = 0x1ff7fffd000LL;	res += 1LL << (bits-2);	res += 1LL << (2*(bits-2));	res += 1LL << (3*(bits-2));	res <<= bits;	if (res > upper_limit)		res = upper_limit;	return res;}static ext4_fsblk_t descriptor_loc(struct super_block *sb,				ext4_fsblk_t logical_sb_block, int nr){	struct ext4_sb_info *sbi = EXT4_SB(sb);	unsigned long bg, first_meta_bg;	int has_super = 0;	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||	    nr < first_meta_bg)		return logical_sb_block + nr + 1;	bg = sbi->s_desc_per_block * nr;	if (ext4_bg_has_super(sb, bg))		has_super = 1;	return (has_super + ext4_group_first_block_no(sb, bg));}static int ext4_fill_super (struct super_block *sb, void *data, int silent){	struct buffer_head * bh;	struct ext4_super_block *es = NULL;	struct ext4_sb_info *sbi;	ext4_fsblk_t block;	ext4_fsblk_t sb_block = get_sb_block(&data);	ext4_fsblk_t logical_sb_block;	unsigned long offset = 0;	unsigned int journal_inum = 0;	unsigned long journal_devnum = 0;	unsigned long def_mount_opts;	struct inode *root;	int blocksize;	int hblock;	int db_count;	int i;	int needs_recovery;	__le32 features;	__u64 blocks_count;	int err;	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);	if (!sbi)		return -ENOMEM;	sb->s_fs_info = sbi;	sbi->s_mount_opt = 0;	sbi->s_resuid = EXT4_DEF_RESUID;	sbi->s_resgid = EXT4_DEF_RESGID;	sbi->s_sb_block = sb_block;	unlock_kernel();	blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);	if (!blocksize) {		printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");		goto out_fail;	}	/*	 * The ext4 superblock will not be buffer aligned for other than 1kB	 * block sizes.  We need to calculate the offset from buffer start.	 */	if (blocksize != EXT4_MIN_BLOCK_SIZE) {		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;		offset = do_div(logical_sb_block, blocksize);	} else {		logical_sb_block = sb_block;	}	if (!(bh = sb_bread(sb, logical_sb_block))) {		printk (KERN_ERR "EXT4-fs: unable to read superblock\n");		goto out_fail;	}	/*	 * Note: s_es must be initialized as soon as possible because	 *       some ext4 macro-instructions depend on its value	 */	es = (struct ext4_super_block *) (((char *)bh->b_data) + offset);	sbi->s_es = es;	sb->s_magic = le16_to_cpu(es->s_magic);	if (sb->s_magic != EXT4_SUPER_MAGIC)		goto cantfind_ext4;	/* Set defaults before we parse the mount options */	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);	if (def_mount_opts & EXT4_DEFM_DEBUG)		set_opt(sbi->s_mount_opt, DEBUG);	if (def_mount_opts & EXT4_DEFM_BSDGROUPS)		set_opt(sbi->s_mount_opt, GRPID);	if (def_mount_opts & EXT4_DEFM_UID16)		set_opt(sbi->s_mount_opt, NO_UID32);#ifdef CONFIG_EXT4DEV_FS_XATTR	if (def_mount_opts & EXT4_DEFM_XATTR_USER)		set_opt(sbi->s_mount_opt, XATTR_USER);#endif#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL	if (def_mount_opts & EXT4_DEFM_ACL)		set_opt(sbi->s_mount_opt, POSIX_ACL);#endif	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)		sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)		sbi->s_mount_opt |= EXT4_MOUNT_ORDERED_DATA;	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)		sbi->s_mount_opt |= EXT4_MOUNT_WRITEBACK_DATA;	if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)		set_opt(sbi->s_mount_opt, ERRORS_PANIC);	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_RO)		set_opt(sbi->s_mount_opt, ERRORS_RO);	else		set_opt(sbi->s_mount_opt, ERRORS_CONT);	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);	set_opt(sbi->s_mount_opt, RESERVATION);	/*	 * turn on extents feature by default in ext4 filesystem	 * User -o noextents to turn it off	 */	set_opt(sbi->s_mount_opt, EXTENTS);	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,			    NULL, 0))		goto failed_mount;	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |		((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV &&	    (EXT4_HAS_COMPAT_FEATURE(sb, ~0U) ||	     EXT4_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||	     EXT4_HAS_INCOMPAT_FEATURE(sb, ~0U)))		printk(KERN_WARNING		       "EXT4-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.	 */	features = EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP);	if (features) {		printk(KERN_ERR "EXT4-fs: %s: couldn't mount because of "		       "unsupported optional features (%x).\n",		       sb->s_id, le32_to_cpu(features));		goto failed_mount;	}	features = EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP);	if (!(sb->s_flags & MS_RDONLY) && features) {		printk(KERN_ERR "EXT4-fs: %s: couldn't mount RDWR because of "		       "unsupported optional features (%x).\n",		       sb->s_id, le32_to_cpu(features));		goto failed_mount;	}	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);	if (blocksize < EXT4_MIN_BLOCK_SIZE ||	    blocksize > EXT4_MAX_BLOCK_SIZE) {		printk(KERN_ERR		       "EXT4-fs: Unsupported filesystem blocksize %d on %s.\n",		       blocksize, sb->s_id);		goto failed_mount;	}	hblock = bdev_hardsect_size(sb->s_bdev);	if (sb->s_blocksize != blocksize) {		/*		 * Make sure the blocksize for the filesystem is larger		 * than the hardware sectorsize for the machine.		 */		if (blocksize < hblock) {			printk(KERN_ERR "EXT4-fs: blocksize %d too small for "			       "device blocksize %d.\n", blocksize, hblock);			goto failed_mount;		}		brelse (bh);		sb_set_blocksize(sb, blocksize);		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;		offset = do_div(logical_sb_block, blocksize);		bh = sb_bread(sb, logical_sb_block);		if (!bh) {			printk(KERN_ERR			       "EXT4-fs: Can't read superblock on 2nd try.\n");			goto failed_mount;		}		es = (struct ext4_super_block *)(((char *)bh->b_data) + offset);		sbi->s_es = es;		if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {			printk (KERN_ERR				"EXT4-fs: Magic mismatch, very weird !\n");			goto failed_mount;		}	}	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits);	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;		sbi->s_first_ino = EXT4_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 < EXT4_GOOD_OLD_INODE_SIZE) ||		    (!is_power_of_2(sbi->s_inode_size)) ||		    (sbi->s_inode_size > blocksize)) {			printk (KERN_ERR				"EXT4-fs: unsupported inode size: %d\n",				sbi->s_inode_size);			goto failed_mount;		}		if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)			sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);	}	sbi->s_desc_size = le16_to_cpu(es->s_desc_size);	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {		if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||		    sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||		    !is_power_of_2(sbi->s_desc_size)) {			printk(KERN_ERR			       "EXT4-fs: unsupported descriptor size %lu\n",			       sbi->s_desc_size);			goto failed_mount;		}	} else		sbi->s_desc_size = EXT4_MIN_DESC_SIZE;	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);	if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)		goto cantfind_ext4;	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);	if (sbi->s_inodes_per_block == 0)		goto cantfind_ext4;

⌨️ 快捷键说明

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