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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  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/module.h>#include <linux/string.h>#include <linux/fs.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/exportfs.h>#include <linux/smp_lock.h>#include <linux/vfs.h>#include <linux/seq_file.h>#include <linux/mount.h>#include <linux/log2.h>#include <asm/uaccess.h>#include "ext2.h"#include "xattr.h"#include "acl.h"#include "xip.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 dentry * dentry, 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);	percpu_counter_destroy(&sbi->s_freeblocks_counter);	percpu_counter_destroy(&sbi->s_freeinodes_counter);	percpu_counter_destroy(&sbi->s_dirs_counter);	brelse (sbi->s_sbh);	sb->s_fs_info = NULL;	kfree(sbi);	return;}static struct kmem_cache * 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, GFP_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->i_block_alloc_info = NULL;	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(struct kmem_cache * cachep, void *foo){	struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;	rwlock_init(&ei->i_meta_lock);#ifdef CONFIG_EXT2_FS_XATTR	init_rwsem(&ei->xattr_sem);#endif	mutex_init(&ei->truncate_mutex);	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|						SLAB_MEM_SPREAD),					     init_once);	if (ext2_inode_cachep == NULL)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	kmem_cache_destroy(ext2_inode_cachep);}static void ext2_clear_inode(struct inode *inode){	struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info;#ifdef CONFIG_EXT2_FS_POSIX_ACL	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;	}#endif	ext2_discard_reservation(inode);	EXT2_I(inode)->i_block_alloc_info = NULL;	if (unlikely(rsv))		kfree(rsv);}static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs){	struct super_block *sb = vfs->mnt_sb;	struct ext2_sb_info *sbi = EXT2_SB(sb);	struct ext2_super_block *es = sbi->s_es;	unsigned long def_mount_opts;	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);	if (sbi->s_sb_block != 1)		seq_printf(seq, ",sb=%lu", sbi->s_sb_block);	if (test_opt(sb, MINIX_DF))		seq_puts(seq, ",minixdf");	if (test_opt(sb, GRPID))		seq_puts(seq, ",grpid");	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS))		seq_puts(seq, ",nogrpid");	if (sbi->s_resuid != EXT2_DEF_RESUID ||	    le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) {		seq_printf(seq, ",resuid=%u", sbi->s_resuid);	}	if (sbi->s_resgid != EXT2_DEF_RESGID ||	    le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) {		seq_printf(seq, ",resgid=%u", sbi->s_resgid);	}	if (test_opt(sb, ERRORS_CONT)) {		int def_errors = le16_to_cpu(es->s_errors);		if (def_errors == EXT2_ERRORS_PANIC ||		    def_errors == EXT2_ERRORS_RO) {			seq_puts(seq, ",errors=continue");		}	}	if (test_opt(sb, ERRORS_RO))		seq_puts(seq, ",errors=remount-ro");	if (test_opt(sb, ERRORS_PANIC))		seq_puts(seq, ",errors=panic");	if (test_opt(sb, NO_UID32))		seq_puts(seq, ",nouid32");	if (test_opt(sb, DEBUG))		seq_puts(seq, ",debug");	if (test_opt(sb, OLDALLOC))		seq_puts(seq, ",oldalloc");#ifdef CONFIG_EXT2_FS_XATTR	if (test_opt(sb, XATTR_USER))		seq_puts(seq, ",user_xattr");	if (!test_opt(sb, XATTR_USER) &&	    (def_mount_opts & EXT2_DEFM_XATTR_USER)) {		seq_puts(seq, ",nouser_xattr");	}#endif#ifdef CONFIG_EXT2_FS_POSIX_ACL	if (test_opt(sb, POSIX_ACL))		seq_puts(seq, ",acl");	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT2_DEFM_ACL))		seq_puts(seq, ",noacl");#endif	if (test_opt(sb, NOBH))		seq_puts(seq, ",nobh");#if defined(CONFIG_QUOTA)	if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)		seq_puts(seq, ",usrquota");	if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA)		seq_puts(seq, ",grpquota");#endif#if defined(CONFIG_EXT2_FS_XIP)	if (sbi->s_mount_opt & EXT2_MOUNT_XIP)		seq_puts(seq, ",xip");#endif	return 0;}#ifdef CONFIG_QUOTAstatic ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off);static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);#endifstatic const 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,	.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,	.show_options	= ext2_show_options,#ifdef CONFIG_QUOTA	.quota_read	= ext2_quota_read,	.quota_write	= ext2_quota_write,#endif};static struct inode *ext2_nfs_get_inode(struct super_block *sb,		u64 ino, u32 generation){	struct inode *inode;	if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO)		return ERR_PTR(-ESTALE);	if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))		return ERR_PTR(-ESTALE);	/* iget isn't really right if the inode is currently unallocated!!	 * ext2_read_inode currently does appropriate checks, but	 * it might be "neater" to call ext2_get_inode first and check	 * if the inode is valid.....	 */	inode = iget(sb, ino);	if (inode == NULL)		return ERR_PTR(-ENOMEM);	if (is_bad_inode(inode) ||	    (generation && inode->i_generation != generation)) {		/* we didn't find the right inode.. */		iput(inode);		return ERR_PTR(-ESTALE);	}	return inode;}static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid,		int fh_len, int fh_type){	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,				    ext2_nfs_get_inode);}static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid,		int fh_len, int fh_type){	return generic_fh_to_parent(sb, fid, fh_len, fh_type,				    ext2_nfs_get_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. */static const struct export_operations ext2_export_ops = {	.fh_to_dentry = ext2_fh_to_dentry,	.fh_to_parent = ext2_fh_to_parent,	.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_nocheck, Opt_debug,	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,	Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,	Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation};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_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_xip, "xip"},	{Opt_grpquota, "grpquota"},	{Opt_ignore, "noquota"},	{Opt_quota, "quota"},	{Opt_usrquota, "usrquota"},	{Opt_reservation, "reservation"},	{Opt_noreservation, "noreservation"},	{Opt_err, NULL}};static int parse_options (char * options,			  struct ext2_sb_info *sbi){	char * p;	substring_t args[MAX_OPT_ARGS];	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;

⌨️ 快捷键说明

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