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

📄 super.c

📁 嵌入式系统设计与实例开发源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		fsync_no_super(j_dev);		invalidate_buffers(j_dev);		ext3_blkdev_remove(sbi);	}	clear_ro_after(sb);	return;}static struct super_operations ext3_sops = {	read_inode:	ext3_read_inode,	/* BKL held */	write_inode:	ext3_write_inode,	/* BKL not held.  Don't need */	dirty_inode:	ext3_dirty_inode,	/* BKL not held.  We take it */	put_inode:	ext3_put_inode,		/* BKL not held.  Don't need */	delete_inode:	ext3_delete_inode,	/* BKL not held.  We take it */	put_super:	ext3_put_super,		/* BKL held */	write_super:	ext3_write_super,	/* BKL held */	write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */	unlockfs:	ext3_unlockfs,		/* BKL not held.  We take it */	statfs:		ext3_statfs,		/* BKL held */	remount_fs:	ext3_remount,		/* BKL held */};static int want_value(char *value, char *option){	if (!value || !*value) {		printk(KERN_NOTICE "EXT3-fs: the %s option needs an argument\n",		       option);		return -1;	}	return 0;}static int want_null_value(char *value, char *option){	if (*value) {		printk(KERN_NOTICE "EXT3-fs: Invalid %s argument: %s\n",		       option, value);		return -1;	}	return 0;}static int want_numeric(char *value, char *option, unsigned long *number){	if (want_value(value, option))		return -1;	*number = simple_strtoul(value, &value, 0);	if (want_null_value(value, option))		return -1;	return 0;}/* * This function has been shamelessly adapted from the msdos fs */static int parse_options (char * options, unsigned long * sb_block,			  struct ext3_sb_info *sbi,			  unsigned long * inum,			  int is_remount){	unsigned long *mount_options = &sbi->s_mount_opt;	uid_t *resuid = &sbi->s_resuid;	gid_t *resgid = &sbi->s_resgid;	char * this_char;	char * value;	if (!options)		return 1;	for (this_char = strtok (options, ",");	     this_char != NULL;	     this_char = strtok (NULL, ",")) {		if ((value = strchr (this_char, '=')) != NULL)			*value++ = 0;		if (!strcmp (this_char, "bsddf"))			clear_opt (*mount_options, MINIX_DF);		else if (!strcmp (this_char, "nouid32")) {			set_opt (*mount_options, NO_UID32);		}		else if (!strcmp (this_char, "abort"))			set_opt (*mount_options, ABORT);		else if (!strcmp (this_char, "check")) {			if (!value || !*value || !strcmp (value, "none"))				clear_opt (*mount_options, CHECK);			else#ifdef CONFIG_EXT3_CHECK				set_opt (*mount_options, CHECK);#else				printk(KERN_ERR 				       "EXT3 Check option not supported\n");#endif		}		else if (!strcmp (this_char, "debug"))			set_opt (*mount_options, DEBUG);		else if (!strcmp (this_char, "errors")) {			if (want_value(value, "errors"))				return 0;			if (!strcmp (value, "continue")) {				clear_opt (*mount_options, ERRORS_RO);				clear_opt (*mount_options, ERRORS_PANIC);				set_opt (*mount_options, ERRORS_CONT);			}			else if (!strcmp (value, "remount-ro")) {				clear_opt (*mount_options, ERRORS_CONT);				clear_opt (*mount_options, ERRORS_PANIC);				set_opt (*mount_options, ERRORS_RO);			}			else if (!strcmp (value, "panic")) {				clear_opt (*mount_options, ERRORS_CONT);				clear_opt (*mount_options, ERRORS_RO);				set_opt (*mount_options, ERRORS_PANIC);			}			else {				printk (KERN_ERR					"EXT3-fs: Invalid errors option: %s\n",					value);				return 0;			}		}		else if (!strcmp (this_char, "grpid") ||			 !strcmp (this_char, "bsdgroups"))			set_opt (*mount_options, GRPID);		else if (!strcmp (this_char, "minixdf"))			set_opt (*mount_options, MINIX_DF);		else if (!strcmp (this_char, "nocheck"))			clear_opt (*mount_options, CHECK);		else if (!strcmp (this_char, "nogrpid") ||			 !strcmp (this_char, "sysvgroups"))			clear_opt (*mount_options, GRPID);		else if (!strcmp (this_char, "resgid")) {			unsigned long v;			if (want_numeric(value, "resgid", &v))				return 0;			*resgid = v;		}		else if (!strcmp (this_char, "resuid")) {			unsigned long v;			if (want_numeric(value, "resuid", &v))				return 0;			*resuid = v;		}		else if (!strcmp (this_char, "sb")) {			if (want_numeric(value, "sb", sb_block))				return 0;		}#ifdef CONFIG_JBD_DEBUG		else if (!strcmp (this_char, "ro-after")) {			unsigned long v;			if (want_numeric(value, "ro-after", &v))				return 0;			ext3_ro_after = v;		}#endif		/* Silently ignore the quota options */		else if (!strcmp (this_char, "grpquota")		         || !strcmp (this_char, "noquota")		         || !strcmp (this_char, "quota")		         || !strcmp (this_char, "usrquota"))			/* Don't do anything ;-) */ ;		else if (!strcmp (this_char, "journal")) {			/* @@@ FIXME */			/* Eventually we will want to be able to create                           a journal file here.  For now, only allow the                           user to specify an existing inode to be the                           journal file. */			if (is_remount) {				printk(KERN_ERR "EXT3-fs: cannot specify "				       "journal on remount\n");				return 0;			}			if (want_value(value, "journal"))				return 0;			if (!strcmp (value, "update"))				set_opt (*mount_options, UPDATE_JOURNAL);			else if (want_numeric(value, "journal", inum))				return 0;		}		else if (!strcmp (this_char, "noload"))			set_opt (*mount_options, NOLOAD);		else if (!strcmp (this_char, "data")) {			int data_opt = 0;			if (want_value(value, "data"))				return 0;			if (!strcmp (value, "journal"))				data_opt = EXT3_MOUNT_JOURNAL_DATA;			else if (!strcmp (value, "ordered"))				data_opt = EXT3_MOUNT_ORDERED_DATA;			else if (!strcmp (value, "writeback"))				data_opt = EXT3_MOUNT_WRITEBACK_DATA;			else {				printk (KERN_ERR 					"EXT3-fs: Invalid data option: %s\n",					value);				return 0;			}			if (is_remount) {				if ((*mount_options & EXT3_MOUNT_DATA_FLAGS) !=							data_opt) {					printk(KERN_ERR					       "EXT3-fs: cannot change data "					       "mode on remount\n");					return 0;				}			} else {				*mount_options &= ~EXT3_MOUNT_DATA_FLAGS;				*mount_options |= data_opt;			}		} else {			printk (KERN_ERR 				"EXT3-fs: Unrecognized mount option %s\n",				this_char);			return 0;		}	}	return 1;}static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,			    int read_only){	struct ext3_sb_info *sbi = EXT3_SB(sb);	int res = 0;	if (le32_to_cpu(es->s_rev_level) > EXT3_MAX_SUPP_REV) {		printk (KERN_ERR "EXT3-fs warning: revision level too high, "			"forcing read-only mode\n");		res = MS_RDONLY;	}	if (read_only)		return res;	if (!(sbi->s_mount_state & EXT3_VALID_FS))		printk (KERN_WARNING "EXT3-fs warning: mounting unchecked fs, "			"running e2fsck is recommended\n");	else if ((sbi->s_mount_state & EXT3_ERROR_FS))		printk (KERN_WARNING			"EXT3-fs warning: mounting fs with errors, "			"running e2fsck is recommended\n");	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&		 le16_to_cpu(es->s_mnt_count) >=		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))		printk (KERN_WARNING			"EXT3-fs warning: maximal mount count reached, "			"running e2fsck is recommended\n");	else if (le32_to_cpu(es->s_checkinterval) &&		(le32_to_cpu(es->s_lastcheck) +			le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))		printk (KERN_WARNING			"EXT3-fs warning: checktime reached, "			"running e2fsck is recommended\n");#if 0		/* @@@ We _will_ want to clear the valid bit if we find                   inconsistencies, to force a fsck at reboot.  But for                   a plain journaled filesystem we can keep it set as                   valid forever! :) */	es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS);#endif	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))		es->s_max_mnt_count =			(__s16) cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);	es->s_mtime = cpu_to_le32(CURRENT_TIME);	ext3_update_dynamic_rev(sb);	EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);	ext3_commit_super (sb, es, 1);	if (test_opt (sb, DEBUG))		printk (KERN_INFO			"[EXT3 FS %s, %s, bs=%lu, gc=%lu, "			"bpg=%lu, ipg=%lu, mo=%04lx]\n",			EXT3FS_VERSION, EXT3FS_DATE, sb->s_blocksize,			sbi->s_groups_count,			EXT3_BLOCKS_PER_GROUP(sb),			EXT3_INODES_PER_GROUP(sb),			sbi->s_mount_opt);	printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",				bdevname(sb->s_dev));	if (EXT3_SB(sb)->s_journal->j_inode == NULL) {		printk("external journal on %s\n",				bdevname(EXT3_SB(sb)->s_journal->j_dev));	} else {		printk("internal journal\n");	}#ifdef CONFIG_EXT3_CHECK	if (test_opt (sb, CHECK)) {		ext3_check_blocks_bitmap (sb);		ext3_check_inodes_bitmap (sb);	}#endif	setup_ro_after(sb);	return res;}static int ext3_check_descriptors (struct super_block * sb){	struct ext3_sb_info *sbi = EXT3_SB(sb);	unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);	struct ext3_group_desc * gdp = NULL;	int desc_block = 0;	int i;	ext3_debug ("Checking group descriptors");	for (i = 0; i < sbi->s_groups_count; i++)	{		if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)			gdp = (struct ext3_group_desc *)					sbi->s_group_desc[desc_block++]->b_data;		if (le32_to_cpu(gdp->bg_block_bitmap) < block ||		    le32_to_cpu(gdp->bg_block_bitmap) >=				block + EXT3_BLOCKS_PER_GROUP(sb))		{			ext3_error (sb, "ext3_check_descriptors",				    "Block bitmap for group %d"				    " not in group (block %lu)!",				    i, (unsigned long)					le32_to_cpu(gdp->bg_block_bitmap));			return 0;		}		if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||		    le32_to_cpu(gdp->bg_inode_bitmap) >=				block + EXT3_BLOCKS_PER_GROUP(sb))		{			ext3_error (sb, "ext3_check_descriptors",				    "Inode bitmap for group %d"				    " not in group (block %lu)!",				    i, (unsigned long)					le32_to_cpu(gdp->bg_inode_bitmap));			return 0;		}		if (le32_to_cpu(gdp->bg_inode_table) < block ||		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=		    block + EXT3_BLOCKS_PER_GROUP(sb))		{			ext3_error (sb, "ext3_check_descriptors",				    "Inode table for group %d"				    " not in group (block %lu)!",				    i, (unsigned long)					le32_to_cpu(gdp->bg_inode_table));			return 0;		}		block += EXT3_BLOCKS_PER_GROUP(sb);		gdp++;	}	return 1;}/* ext3_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 * ext3_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 ext3_orphan_cleanup (struct super_block * sb,				 struct ext3_super_block * es){	unsigned int s_flags = sb->s_flags;	int nr_orphans = 0, nr_truncates = 0;	if (!es->s_last_orphan) {		jbd_debug(4, "no orphan inodes to clean up\n");		return;	}	if (s_flags & MS_RDONLY) {		printk(KERN_INFO "EXT3-fs: %s: orphan cleanup on readonly fs\n",		       bdevname(sb->s_dev));		sb->s_flags &= ~MS_RDONLY;	}	if (sb->u.ext3_sb.s_mount_state & EXT3_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;	}	while (es->s_last_orphan) {		struct inode *inode;		if (!(inode =		      ext3_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {			es->s_last_orphan = 0;			break;		}		list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);		if (inode->i_nlink) {			printk(KERN_DEBUG __FUNCTION__				": truncating inode %ld to %Ld bytes\n",				inode->i_ino, inode->i_size);			jbd_debug(2, "truncating inode %ld to %Ld bytes\n",				  inode->i_ino, inode->i_size);			ext3_truncate(inode);			nr_truncates++;		} else {			printk(KERN_DEBUG __FUNCTION__				": deleting unreferenced inode %ld\n",				inode->i_ino);			jbd_debug(2, "deleting unreferenced inode %ld\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 "EXT3-fs: %s: %d orphan inode%s deleted\n",		       bdevname(sb->s_dev), PLURAL(nr_orphans));	if (nr_truncates)		printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n",		       bdevname(sb->s_dev), PLURAL(nr_truncates));	sb->s_flags = s_flags; /* Restore MS_RDONLY status */}#define log2(n) ffz(~(n))/* * 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 ext3_max_size(int bits){

⌨️ 快捷键说明

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