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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * super.c * * PURPOSE *  Super block routines for the OSTA-UDF(tm) filesystem. * * DESCRIPTION *  OSTA-UDF(tm) = Optical Storage Technology Association *  Universal Disk Format. * *  This code is based on version 2.00 of the UDF specification, *  and revision 3 of the ECMA 167 standard [equivalent to ISO 13346]. *    http://www.osta.org/ *    http://www.ecma.ch/ *    http://www.iso.org/ * * COPYRIGHT *  This file is distributed under the terms of the GNU General Public *  License (GPL). Copies of the GPL can be obtained from: *    ftp://prep.ai.mit.edu/pub/gnu/GPL *  Each contributing author retains all rights to their own work. * *  (C) 1998 Dave Boynton *  (C) 1998-2004 Ben Fennema *  (C) 2000 Stelias Computing Inc * * HISTORY * *  09/24/98 dgb  changed to allow compiling outside of kernel, and *                added some debugging. *  10/01/98 dgb  updated to allow (some) possibility of compiling w/2.0.34 *  10/16/98      attempting some multi-session support *  10/17/98      added freespace count for "df" *  11/11/98 gr   added novrs option *  11/26/98 dgb  added fileset,anchor mount options *  12/06/98 blf  really hosed things royally. vat/sparing support. sequenced vol descs *                rewrote option handling based on isofs *  12/20/98      find the free space bitmap (if it exists) */#include "udfdecl.h"#include <linux/blkdev.h>#include <linux/slab.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/parser.h>#include <linux/stat.h>#include <linux/cdrom.h>#include <linux/nls.h>#include <linux/smp_lock.h>#include <linux/buffer_head.h>#include <linux/vfs.h>#include <linux/vmalloc.h>#include <asm/byteorder.h>#include <linux/udf_fs.h>#include "udf_sb.h"#include "udf_i.h"#include <linux/init.h>#include <asm/uaccess.h>#define VDS_POS_PRIMARY_VOL_DESC	0#define VDS_POS_UNALLOC_SPACE_DESC	1#define VDS_POS_LOGICAL_VOL_DESC	2#define VDS_POS_PARTITION_DESC		3#define VDS_POS_IMP_USE_VOL_DESC	4#define VDS_POS_VOL_DESC_PTR		5#define VDS_POS_TERMINATING_DESC	6#define VDS_POS_LENGTH			7static char error_buf[1024];/* These are the "meat" - everything else is stuffing */static int udf_fill_super(struct super_block *, void *, int);static void udf_put_super(struct super_block *);static void udf_write_super(struct super_block *);static int udf_remount_fs(struct super_block *, int *, char *);static int udf_check_valid(struct super_block *, int, int);static int udf_vrs(struct super_block *sb, int silent);static int udf_load_partition(struct super_block *, kernel_lb_addr *);static int udf_load_logicalvol(struct super_block *, struct buffer_head *,			       kernel_lb_addr *);static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);static void udf_find_anchor(struct super_block *);static int udf_find_fileset(struct super_block *, kernel_lb_addr *,			    kernel_lb_addr *);static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);static void udf_load_fileset(struct super_block *, struct buffer_head *,			     kernel_lb_addr *);static int udf_load_partdesc(struct super_block *, struct buffer_head *);static void udf_open_lvid(struct super_block *);static void udf_close_lvid(struct super_block *);static unsigned int udf_count_free(struct super_block *);static int udf_statfs(struct dentry *, struct kstatfs *);/* UDF filesystem type */static int udf_get_sb(struct file_system_type *fs_type,		      int flags, const char *dev_name, void *data,		      struct vfsmount *mnt){	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt);}static struct file_system_type udf_fstype = {	.owner		= THIS_MODULE,	.name		= "udf",	.get_sb		= udf_get_sb,	.kill_sb	= kill_block_super,	.fs_flags	= FS_REQUIRES_DEV,};static struct kmem_cache *udf_inode_cachep;static struct inode *udf_alloc_inode(struct super_block *sb){	struct udf_inode_info *ei;	ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, GFP_KERNEL);	if (!ei)		return NULL;	ei->i_unique = 0;	ei->i_lenExtents = 0;	ei->i_next_alloc_block = 0;	ei->i_next_alloc_goal = 0;	ei->i_strat4096 = 0;	return &ei->vfs_inode;}static void udf_destroy_inode(struct inode *inode){	kmem_cache_free(udf_inode_cachep, UDF_I(inode));}static void init_once(struct kmem_cache *cachep, void *foo){	struct udf_inode_info *ei = (struct udf_inode_info *)foo;	ei->i_ext.i_data = NULL;	inode_init_once(&ei->vfs_inode);}static int init_inodecache(void){	udf_inode_cachep = kmem_cache_create("udf_inode_cache",					     sizeof(struct udf_inode_info),					     0, (SLAB_RECLAIM_ACCOUNT |						 SLAB_MEM_SPREAD),					     init_once);	if (!udf_inode_cachep)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	kmem_cache_destroy(udf_inode_cachep);}/* Superblock operations */static const struct super_operations udf_sb_ops = {	.alloc_inode	= udf_alloc_inode,	.destroy_inode	= udf_destroy_inode,	.write_inode	= udf_write_inode,	.delete_inode	= udf_delete_inode,	.clear_inode	= udf_clear_inode,	.put_super	= udf_put_super,	.write_super	= udf_write_super,	.statfs		= udf_statfs,	.remount_fs	= udf_remount_fs,};struct udf_options {	unsigned char novrs;	unsigned int blocksize;	unsigned int session;	unsigned int lastblock;	unsigned int anchor;	unsigned int volume;	unsigned short partition;	unsigned int fileset;	unsigned int rootdir;	unsigned int flags;	mode_t umask;	gid_t gid;	uid_t uid;	struct nls_table *nls_map;};static int __init init_udf_fs(void){	int err;	err = init_inodecache();	if (err)		goto out1;	err = register_filesystem(&udf_fstype);	if (err)		goto out;	return 0;out:	destroy_inodecache();out1:	return err;}static void __exit exit_udf_fs(void){	unregister_filesystem(&udf_fstype);	destroy_inodecache();}module_init(init_udf_fs)module_exit(exit_udf_fs)/* * udf_parse_options * * PURPOSE *	Parse mount options. * * DESCRIPTION *	The following mount options are supported: * *	gid=		Set the default group. *	umask=		Set the default umask. *	uid=		Set the default user. *	bs=		Set the block size. *	unhide		Show otherwise hidden files. *	undelete	Show deleted files in lists. *	adinicb		Embed data in the inode (default) *	noadinicb	Don't embed data in the inode *	shortad		Use short ad's *	longad		Use long ad's (default) *	nostrict	Unset strict conformance *	iocharset=	Set the NLS character set * *	The remaining are for debugging and disaster recovery: * *	novrs		Skip volume sequence recognition * *	The following expect a offset from 0. * *	session=	Set the CDROM session (default= last session) *	anchor=		Override standard anchor location. (default= 256) *	volume=		Override the VolumeDesc location. (unused) *	partition=	Override the PartitionDesc location. (unused) *	lastblock=	Set the last block of the filesystem/ * *	The following expect a offset from the partition root. * *	fileset=	Override the fileset block location. (unused) *	rootdir=	Override the root directory location. (unused) *		WARNING: overriding the rootdir to a non-directory may *		yield highly unpredictable results. * * PRE-CONDITIONS *	options		Pointer to mount options string. *	uopts		Pointer to mount options variable. * * POST-CONDITIONS *	<return>	1	Mount options parsed okay. *	<return>	0	Error parsing mount options. * * HISTORY *	July 1, 1997 - Andrew E. Mileski *	Written, tested, and released. */enum {	Opt_novrs, Opt_nostrict, Opt_bs, Opt_unhide, Opt_undelete,	Opt_noadinicb, Opt_adinicb, Opt_shortad, Opt_longad,	Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock,	Opt_anchor, Opt_volume, Opt_partition, Opt_fileset,	Opt_rootdir, Opt_utf8, Opt_iocharset,	Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore};static match_table_t tokens = {	{Opt_novrs,	"novrs"},	{Opt_nostrict,	"nostrict"},	{Opt_bs,	"bs=%u"},	{Opt_unhide,	"unhide"},	{Opt_undelete,	"undelete"},	{Opt_noadinicb,	"noadinicb"},	{Opt_adinicb,	"adinicb"},	{Opt_shortad,	"shortad"},	{Opt_longad,	"longad"},	{Opt_uforget,	"uid=forget"},	{Opt_uignore,	"uid=ignore"},	{Opt_gforget,	"gid=forget"},	{Opt_gignore,	"gid=ignore"},	{Opt_gid,	"gid=%u"},	{Opt_uid,	"uid=%u"},	{Opt_umask,	"umask=%o"},	{Opt_session,	"session=%u"},	{Opt_lastblock,	"lastblock=%u"},	{Opt_anchor,	"anchor=%u"},	{Opt_volume,	"volume=%u"},	{Opt_partition,	"partition=%u"},	{Opt_fileset,	"fileset=%u"},	{Opt_rootdir,	"rootdir=%u"},	{Opt_utf8,	"utf8"},	{Opt_iocharset,	"iocharset=%s"},	{Opt_err,	NULL}};static int udf_parse_options(char *options, struct udf_options *uopt){	char *p;	int option;	uopt->novrs = 0;	uopt->blocksize = 2048;	uopt->partition = 0xFFFF;	uopt->session = 0xFFFFFFFF;	uopt->lastblock = 0;	uopt->anchor = 0;	uopt->volume = 0xFFFFFFFF;	uopt->rootdir = 0xFFFFFFFF;	uopt->fileset = 0xFFFFFFFF;	uopt->nls_map = NULL;	if (!options)		return 1;	while ((p = strsep(&options, ",")) != NULL) {		substring_t args[MAX_OPT_ARGS];		int token;		if (!*p)			continue;		token = match_token(p, tokens, args);		switch (token) {		case Opt_novrs:			uopt->novrs = 1;		case Opt_bs:			if (match_int(&args[0], &option))				return 0;			uopt->blocksize = option;			break;		case Opt_unhide:			uopt->flags |= (1 << UDF_FLAG_UNHIDE);			break;		case Opt_undelete:			uopt->flags |= (1 << UDF_FLAG_UNDELETE);			break;		case Opt_noadinicb:			uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);			break;		case Opt_adinicb:			uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);			break;		case Opt_shortad:			uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);			break;		case Opt_longad:			uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);			break;		case Opt_gid:			if (match_int(args, &option))				return 0;			uopt->gid = option;			uopt->flags |= (1 << UDF_FLAG_GID_SET);			break;		case Opt_uid:			if (match_int(args, &option))				return 0;			uopt->uid = option;			uopt->flags |= (1 << UDF_FLAG_UID_SET);			break;		case Opt_umask:			if (match_octal(args, &option))				return 0;			uopt->umask = option;			break;		case Opt_nostrict:			uopt->flags &= ~(1 << UDF_FLAG_STRICT);			break;		case Opt_session:			if (match_int(args, &option))				return 0;			uopt->session = option;			break;		case Opt_lastblock:			if (match_int(args, &option))				return 0;			uopt->lastblock = option;			break;		case Opt_anchor:			if (match_int(args, &option))				return 0;			uopt->anchor = option;			break;		case Opt_volume:			if (match_int(args, &option))				return 0;			uopt->volume = option;			break;		case Opt_partition:			if (match_int(args, &option))				return 0;			uopt->partition = option;			break;		case Opt_fileset:			if (match_int(args, &option))				return 0;			uopt->fileset = option;			break;		case Opt_rootdir:			if (match_int(args, &option))				return 0;			uopt->rootdir = option;			break;		case Opt_utf8:			uopt->flags |= (1 << UDF_FLAG_UTF8);			break;#ifdef CONFIG_UDF_NLS		case Opt_iocharset:			uopt->nls_map = load_nls(args[0].from);			uopt->flags |= (1 << UDF_FLAG_NLS_MAP);			break;#endif		case Opt_uignore:			uopt->flags |= (1 << UDF_FLAG_UID_IGNORE);			break;		case Opt_uforget:			uopt->flags |= (1 << UDF_FLAG_UID_FORGET);			break;		case Opt_gignore:			uopt->flags |= (1 << UDF_FLAG_GID_IGNORE);			break;		case Opt_gforget:			uopt->flags |= (1 << UDF_FLAG_GID_FORGET);			break;		default:			printk(KERN_ERR "udf: bad mount option \"%s\" "			       "or missing value\n", p);			return 0;		}	}	return 1;}void udf_write_super(struct super_block *sb){	lock_kernel();	if (!(sb->s_flags & MS_RDONLY))		udf_open_lvid(sb);	sb->s_dirt = 0;	unlock_kernel();}

⌨️ 快捷键说明

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