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

📄 super.c

📁 这是Linux系统下的对UDF文件系统新增的功能
💻 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/ * * CONTACTS *  E-mail regarding any portion of the Linux UDF file system should be *  directed to the development team mailing list (run by majordomo): *	  linux_udf@hpesjro.fc.hp.com * * 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/config.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 <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 *, lb_addr *);static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);static void udf_load_logicalvolint(struct super_block *, extent_ad);static void udf_find_anchor(struct super_block *);static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);static void 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 super_block *, struct kstatfs *);/* UDF filesystem type */static struct super_block *udf_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *data){	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super);}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 kmem_cache_t * 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, SLAB_KERNEL);	if (!ei)		return NULL;	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(void * foo, kmem_cache_t * cachep, unsigned long flags){	struct udf_inode_info *ei = (struct udf_inode_info *) foo;	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==	    SLAB_CTOR_CONSTRUCTOR)	{		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_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,					     init_once, NULL);	if (udf_inode_cachep == NULL)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	if (kmem_cache_destroy(udf_inode_cachep))		printk(KERN_INFO "udf_inode_cache: not all structures were freed\n");}/* Superblock operations */static struct super_operations udf_sb_ops = {	.alloc_inode		= udf_alloc_inode,	.destroy_inode		= udf_destroy_inode,	.read_inode		= udf_read_inode,	.write_inode		= udf_write_inode,	.put_inode		= udf_put_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;	printk(KERN_NOTICE "udf: registering filesystem\n");	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){	printk(KERN_NOTICE "udf: unregistering filesystem\n");	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};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_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 intudf_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;				break;			case Opt_uid:				if (match_int(args, &option))					return 0;				uopt->uid = option;				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;#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)			case Opt_iocharset:				uopt->nls_map = load_nls(args[0].from);				uopt->flags |= (1 << UDF_FLAG_NLS_MAP);				break;#endif			default:				printk(KERN_ERR "udf: bad mount option \"%s\" "						"or missing value\n", p);			return 0;		}	}	return 1;}voidudf_write_super(struct super_block *sb){	lock_kernel();	if (!(sb->s_flags & MS_RDONLY))		udf_open_lvid(sb);	sb->s_dirt = 0;	unlock_kernel();}static intudf_remount_fs(struct super_block *sb, int *flags, char *options){	struct udf_options uopt;	uopt.flags = UDF_SB(sb)->s_flags ;	uopt.uid   = UDF_SB(sb)->s_uid ;	uopt.gid   = UDF_SB(sb)->s_gid ;	uopt.umask = UDF_SB(sb)->s_umask ;	if ( !udf_parse_options(options, &uopt) )		return -EINVAL;	UDF_SB(sb)->s_flags = uopt.flags;	UDF_SB(sb)->s_uid   = uopt.uid;	UDF_SB(sb)->s_gid   = uopt.gid;	UDF_SB(sb)->s_umask = uopt.umask;	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))		return 0;	if (*flags & MS_RDONLY)		udf_close_lvid(sb);	else		udf_open_lvid(sb);	return 0;}/* * udf_set_blocksize * * PURPOSE *	Set the block size to be used in all transfers. * * DESCRIPTION *	To allow room for a DMA transfer, it is best to guess big when unsure. *	This routine picks 2048 bytes as the blocksize when guessing. This *	should be adequate until devices with larger block sizes become common. *

⌨️ 快捷键说明

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