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

📄 super.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/ext2/super.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * *  from * *  linux/fs/minix/inode.c * *  Copyright (C) 1991, 1992  Linus Torvalds * *  Big-endian to little-endian byte-swapping/bitmaps by *        David S. Miller (davem@caip.rutgers.edu), 1995 */#include <linux/config.h>#include <linux/module.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/parser.h>#include <linux/random.h>#include <linux/buffer_head.h>#include <linux/smp_lock.h>#include <linux/vfs.h>#include <asm/uaccess.h>#include "ext2.h"#include "xattr.h"#include "acl.h"static void ext2_sync_super(struct super_block *sb,			    struct ext2_super_block *es);static int ext2_remount (struct super_block * sb, int * flags, char * data);static int ext2_statfs (struct super_block * sb, struct kstatfs * buf);void ext2_error (struct super_block * sb, const char * function,		 const char * fmt, ...){	va_list args;	struct ext2_sb_info *sbi = EXT2_SB(sb);	struct ext2_super_block *es = sbi->s_es;	if (!(sb->s_flags & MS_RDONLY)) {		sbi->s_mount_state |= EXT2_ERROR_FS;		es->s_state =			cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);		ext2_sync_super(sb, es);	}	va_start(args, fmt);	printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function);	vprintk(fmt, args);	printk("\n");	va_end(args);	if (test_opt(sb, ERRORS_PANIC))		panic("EXT2-fs panic from previous error\n");	if (test_opt(sb, ERRORS_RO)) {		printk("Remounting filesystem read-only\n");		sb->s_flags |= MS_RDONLY;	}}void ext2_warning (struct super_block * sb, const char * function,		   const char * fmt, ...){	va_list args;	va_start(args, fmt);	printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ",	       sb->s_id, function);	vprintk(fmt, args);	printk("\n");	va_end(args);}void ext2_update_dynamic_rev(struct super_block *sb){	struct ext2_super_block *es = EXT2_SB(sb)->s_es;	if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)		return;	ext2_warning(sb, __FUNCTION__,		     "updating to rev %d because of new feature flag, "		     "running e2fsck is recommended",		     EXT2_DYNAMIC_REV);	es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);	es->s_inode_size = cpu_to_le16(EXT2_GOOD_OLD_INODE_SIZE);	es->s_rev_level = cpu_to_le32(EXT2_DYNAMIC_REV);	/* leave es->s_feature_*compat flags alone */	/* es->s_uuid will be set by e2fsck if empty */	/*	 * The rest of the superblock fields should be zero, and if not it	 * means they are likely already in use, so leave them alone.  We	 * can leave it up to e2fsck to clean up any inconsistencies there.	 */}static void ext2_put_super (struct super_block * sb){	int db_count;	int i;	struct ext2_sb_info *sbi = EXT2_SB(sb);	ext2_xattr_put_super(sb);	if (!(sb->s_flags & MS_RDONLY)) {		struct ext2_super_block *es = sbi->s_es;		es->s_state = cpu_to_le16(sbi->s_mount_state);		ext2_sync_super(sb, es);	}	db_count = sbi->s_gdb_count;	for (i = 0; i < db_count; i++)		if (sbi->s_group_desc[i])			brelse (sbi->s_group_desc[i]);	kfree(sbi->s_group_desc);	kfree(sbi->s_debts);	brelse (sbi->s_sbh);	sb->s_fs_info = NULL;	kfree(sbi);	return;}static kmem_cache_t * ext2_inode_cachep;static struct inode *ext2_alloc_inode(struct super_block *sb){	struct ext2_inode_info *ei;	ei = (struct ext2_inode_info *)kmem_cache_alloc(ext2_inode_cachep, SLAB_KERNEL);	if (!ei)		return NULL;#ifdef CONFIG_EXT2_FS_POSIX_ACL	ei->i_acl = EXT2_ACL_NOT_CACHED;	ei->i_default_acl = EXT2_ACL_NOT_CACHED;#endif	ei->vfs_inode.i_version = 1;	return &ei->vfs_inode;}static void ext2_destroy_inode(struct inode *inode){	kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));}static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags){	struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==	    SLAB_CTOR_CONSTRUCTOR) {		rwlock_init(&ei->i_meta_lock);#ifdef CONFIG_EXT2_FS_XATTR		init_rwsem(&ei->xattr_sem);#endif		inode_init_once(&ei->vfs_inode);	}} static int init_inodecache(void){	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",					     sizeof(struct ext2_inode_info),					     0, SLAB_RECLAIM_ACCOUNT,					     init_once, NULL);	if (ext2_inode_cachep == NULL)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	if (kmem_cache_destroy(ext2_inode_cachep))		printk(KERN_INFO "ext2_inode_cache: not all structures were freed\n");}#ifdef CONFIG_EXT2_FS_POSIX_ACLstatic void ext2_clear_inode(struct inode *inode){	struct ext2_inode_info *ei = EXT2_I(inode);	if (ei->i_acl && ei->i_acl != EXT2_ACL_NOT_CACHED) {		posix_acl_release(ei->i_acl);		ei->i_acl = EXT2_ACL_NOT_CACHED;	}	if (ei->i_default_acl && ei->i_default_acl != EXT2_ACL_NOT_CACHED) {		posix_acl_release(ei->i_default_acl);		ei->i_default_acl = EXT2_ACL_NOT_CACHED;	}}#else# define ext2_clear_inode NULL#endifstatic struct super_operations ext2_sops = {	.alloc_inode	= ext2_alloc_inode,	.destroy_inode	= ext2_destroy_inode,	.read_inode	= ext2_read_inode,	.write_inode	= ext2_write_inode,	.put_inode	= ext2_put_inode,	.delete_inode	= ext2_delete_inode,	.put_super	= ext2_put_super,	.write_super	= ext2_write_super,	.statfs		= ext2_statfs,	.remount_fs	= ext2_remount,	.clear_inode	= ext2_clear_inode,};/* Yes, most of these are left as NULL!! * A NULL value implies the default, which works with ext2-like file * systems, but can be improved upon. * Currently only get_parent is required. */struct dentry *ext2_get_parent(struct dentry *child);static struct export_operations ext2_export_ops = {	.get_parent = ext2_get_parent,};static unsigned long get_sb_block(void **data){	unsigned long 	sb_block;	char 		*options = (char *) *data;	if (!options || strncmp(options, "sb=", 3) != 0)		return 1;	/* Default location */	options += 3;	sb_block = simple_strtoul(options, &options, 0);	if (*options && *options != ',') {		printk("EXT2-fs: Invalid sb specification: %s\n",		       (char *) *data);		return 1;	}	if (*options == ',')		options++;	*data = (void *) options;	return sb_block;}enum {	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,	Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,	Opt_ignore, Opt_err,};static match_table_t tokens = {	{Opt_bsd_df, "bsddf"},	{Opt_minix_df, "minixdf"},	{Opt_grpid, "grpid"},	{Opt_grpid, "bsdgroups"},	{Opt_nogrpid, "nogrpid"},	{Opt_nogrpid, "sysvgroups"},	{Opt_resgid, "resgid=%u"},	{Opt_resuid, "resuid=%u"},	{Opt_sb, "sb=%u"},	{Opt_err_cont, "errors=continue"},	{Opt_err_panic, "errors=panic"},	{Opt_err_ro, "errors=remount-ro"},	{Opt_nouid32, "nouid32"},	{Opt_nocheck, "check=none"},	{Opt_nocheck, "nocheck"},	{Opt_check, "check"},	{Opt_debug, "debug"},	{Opt_oldalloc, "oldalloc"},	{Opt_orlov, "orlov"},	{Opt_nobh, "nobh"},	{Opt_user_xattr, "user_xattr"},	{Opt_nouser_xattr, "nouser_xattr"},	{Opt_acl, "acl"},	{Opt_noacl, "noacl"},	{Opt_ignore, "grpquota"},	{Opt_ignore, "noquota"},	{Opt_ignore, "quota"},	{Opt_ignore, "usrquota"},	{Opt_err, NULL}};static int parse_options (char * options,			  struct ext2_sb_info *sbi){	char * p;	substring_t args[MAX_OPT_ARGS];	unsigned long kind = EXT2_MOUNT_ERRORS_CONT;	int option;	if (!options)		return 1;	while ((p = strsep (&options, ",")) != NULL) {		int token;		if (!*p)			continue;		token = match_token(p, tokens, args);		switch (token) {		case Opt_bsd_df:			clear_opt (sbi->s_mount_opt, MINIX_DF);			break;		case Opt_minix_df:			set_opt (sbi->s_mount_opt, MINIX_DF);			break;		case Opt_grpid:			set_opt (sbi->s_mount_opt, GRPID);			break;		case Opt_nogrpid:			clear_opt (sbi->s_mount_opt, GRPID);			break;		case Opt_resuid:			if (match_int(&args[0], &option))				return 0;			sbi->s_resuid = option;			break;		case Opt_resgid:			if (match_int(&args[0], &option))				return 0;			sbi->s_resgid = option;			break;		case Opt_sb:			/* handled by get_sb_block() instead of here */			/* *sb_block = match_int(&args[0]); */			break;		case Opt_err_panic:			kind = EXT2_MOUNT_ERRORS_PANIC;			break;		case Opt_err_ro:			kind = EXT2_MOUNT_ERRORS_RO;			break;		case Opt_err_cont:			kind = EXT2_MOUNT_ERRORS_CONT;			break;		case Opt_nouid32:			set_opt (sbi->s_mount_opt, NO_UID32);			break;		case Opt_check:#ifdef CONFIG_EXT2_CHECK			set_opt (sbi->s_mount_opt, CHECK);#else			printk("EXT2 Check option not supported\n");#endif			break;		case Opt_nocheck:			clear_opt (sbi->s_mount_opt, CHECK);			break;		case Opt_debug:			set_opt (sbi->s_mount_opt, DEBUG);			break;		case Opt_oldalloc:			set_opt (sbi->s_mount_opt, OLDALLOC);			break;		case Opt_orlov:			clear_opt (sbi->s_mount_opt, OLDALLOC);			break;		case Opt_nobh:			set_opt (sbi->s_mount_opt, NOBH);			break;#ifdef CONFIG_EXT2_FS_XATTR		case Opt_user_xattr:			set_opt (sbi->s_mount_opt, XATTR_USER);			break;		case Opt_nouser_xattr:			clear_opt (sbi->s_mount_opt, XATTR_USER);			break;#else		case Opt_user_xattr:		case Opt_nouser_xattr:			printk("EXT2 (no)user_xattr options not supported\n");			break;#endif#ifdef CONFIG_EXT2_FS_POSIX_ACL		case Opt_acl:			set_opt(sbi->s_mount_opt, POSIX_ACL);			break;		case Opt_noacl:			clear_opt(sbi->s_mount_opt, POSIX_ACL);			break;#else		case Opt_acl:		case Opt_noacl:			printk("EXT2 (no)acl options not supported\n");			break;#endif		case Opt_ignore:			break;		default:			return 0;		}	}	sbi->s_mount_opt |= kind;	return 1;}static int ext2_setup_super (struct super_block * sb,			      struct ext2_super_block * es,			      int read_only){	int res = 0;	struct ext2_sb_info *sbi = EXT2_SB(sb);	if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {		printk ("EXT2-fs warning: revision level too high, "			"forcing read-only mode\n");		res = MS_RDONLY;	}	if (read_only)		return res;	if (!(sbi->s_mount_state & EXT2_VALID_FS))		printk ("EXT2-fs warning: mounting unchecked fs, "			"running e2fsck is recommended\n");	else if ((sbi->s_mount_state & EXT2_ERROR_FS))		printk ("EXT2-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 ("EXT2-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) <= get_seconds()))		printk ("EXT2-fs warning: checktime reached, "			"running e2fsck is recommended\n");	if (!le16_to_cpu(es->s_max_mnt_count))		es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);	ext2_write_super(sb);	if (test_opt (sb, DEBUG))		printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "			"bpg=%lu, ipg=%lu, mo=%04lx]\n",			EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,			sbi->s_frag_size,			sbi->s_groups_count,			EXT2_BLOCKS_PER_GROUP(sb),			EXT2_INODES_PER_GROUP(sb),			sbi->s_mount_opt);#ifdef CONFIG_EXT2_CHECK	if (test_opt (sb, CHECK)) {		ext2_check_blocks_bitmap (sb);		ext2_check_inodes_bitmap (sb);	}#endif	return res;}static int ext2_check_descriptors (struct super_block * sb){	int i;	int desc_block = 0;	struct ext2_sb_info *sbi = EXT2_SB(sb);	unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);	struct ext2_group_desc * gdp = NULL;	ext2_debug ("Checking group descriptors");	for (i = 0; i < sbi->s_groups_count; i++)	{		if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)			gdp = (struct ext2_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 + EXT2_BLOCKS_PER_GROUP(sb))		{			ext2_error (sb, "ext2_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 + EXT2_BLOCKS_PER_GROUP(sb))		{			ext2_error (sb, "ext2_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 + EXT2_BLOCKS_PER_GROUP(sb))		{			ext2_error (sb, "ext2_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 += EXT2_BLOCKS_PER_GROUP(sb);		gdp++;	}	return 1;}#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 ext2_max_size(int bits){	loff_t res = EXT2_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;

⌨️ 快捷键说明

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