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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/fat/inode.c * *  Written 1992,1993 by Werner Almesberger *  VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner *  Rewritten for the constant inumbers support by Al Viro * *  Fixes: * *  	Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 */#include <linux/module.h>#include <linux/time.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/seq_file.h>#include <linux/msdos_fs.h>#include <linux/pagemap.h>#include <linux/buffer_head.h>#include <linux/mount.h>#include <linux/vfs.h>#include <linux/parser.h>#include <asm/unaligned.h>#ifndef CONFIG_FAT_DEFAULT_IOCHARSET/* if user don't select VFAT, this is undefined. */#define CONFIG_FAT_DEFAULT_IOCHARSET	""#endifstatic int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;/* * New FAT inode stuff. We do the following: *	a) i_ino is constant and has nothing with on-disk location. *	b) FAT manages its own cache of directory entries. *	c) *This* cache is indexed by on-disk location. *	d) inode has an associated directory entry, all right, but *		it may be unhashed. *	e) currently entries are stored within struct inode. That should *		change. *	f) we deal with races in the following way: *		1. readdir() and lookup() do FAT-dir-cache lookup. *		2. rename() unhashes the F-d-c entry and rehashes it in *			a new place. *		3. unlink() and rmdir() unhash F-d-c entry. *		4. fat_write_inode() checks whether the thing is unhashed. *			If it is we silently return. If it isn't we do bread(), *			check if the location is still valid and retry if it *			isn't. Otherwise we do changes. *		5. Spinlock is used to protect hash/unhash/location check/lookup *		6. fat_clear_inode() unhashes the F-d-c entry. *		7. lookup() and readdir() do igrab() if they find a F-d-c entry *			and consider negative result as cache miss. */#define FAT_HASH_BITS	8#define FAT_HASH_SIZE	(1UL << FAT_HASH_BITS)#define FAT_HASH_MASK	(FAT_HASH_SIZE-1)static struct list_head fat_inode_hashtable[FAT_HASH_SIZE];static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;void fat_hash_init(void){	int i;	for(i = 0; i < FAT_HASH_SIZE; i++) {		INIT_LIST_HEAD(&fat_inode_hashtable[i]);	}}static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos){	unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb;	tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2);	return tmp & FAT_HASH_MASK;}void fat_attach(struct inode *inode, loff_t i_pos){	spin_lock(&fat_inode_lock);	MSDOS_I(inode)->i_pos = i_pos;	list_add(&MSDOS_I(inode)->i_fat_hash,		fat_inode_hashtable + fat_hash(inode->i_sb, i_pos));	spin_unlock(&fat_inode_lock);}void fat_detach(struct inode *inode){	spin_lock(&fat_inode_lock);	MSDOS_I(inode)->i_pos = 0;	list_del_init(&MSDOS_I(inode)->i_fat_hash);	spin_unlock(&fat_inode_lock);}struct inode *fat_iget(struct super_block *sb, loff_t i_pos){	struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos);	struct list_head *walk;	struct msdos_inode_info *i;	struct inode *inode = NULL;	spin_lock(&fat_inode_lock);	list_for_each(walk, p) {		i = list_entry(walk, struct msdos_inode_info, i_fat_hash);		if (i->vfs_inode.i_sb != sb)			continue;		if (i->i_pos != i_pos)			continue;		inode = igrab(&i->vfs_inode);		if (inode)			break;	}	spin_unlock(&fat_inode_lock);	return inode;}static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);struct inode *fat_build_inode(struct super_block *sb,			struct msdos_dir_entry *de, loff_t i_pos, int *res){	struct inode *inode;	*res = 0;	inode = fat_iget(sb, i_pos);	if (inode)		goto out;	inode = new_inode(sb);	*res = -ENOMEM;	if (!inode)		goto out;	inode->i_ino = iunique(sb, MSDOS_ROOT_INO);	inode->i_version = 1;	*res = fat_fill_inode(inode, de);	if (*res < 0) {		iput(inode);		inode = NULL;		goto out;	}	fat_attach(inode, i_pos);	insert_inode_hash(inode);out:	return inode;}void fat_delete_inode(struct inode *inode){	if (!is_bad_inode(inode)) {		inode->i_size = 0;		fat_truncate(inode);	}	clear_inode(inode);}void fat_clear_inode(struct inode *inode){	if (is_bad_inode(inode))		return;	lock_kernel();	spin_lock(&fat_inode_lock);	fat_cache_inval_inode(inode);	list_del_init(&MSDOS_I(inode)->i_fat_hash);	spin_unlock(&fat_inode_lock);	unlock_kernel();}void fat_put_super(struct super_block *sb){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	if (!(sb->s_flags & MS_RDONLY))		fat_clusters_flush(sb);	if (sbi->nls_disk) {		unload_nls(sbi->nls_disk);		sbi->nls_disk = NULL;		sbi->options.codepage = fat_default_codepage;	}	if (sbi->nls_io) {		unload_nls(sbi->nls_io);		sbi->nls_io = NULL;	}	if (sbi->options.iocharset != fat_default_iocharset) {		kfree(sbi->options.iocharset);		sbi->options.iocharset = fat_default_iocharset;	}	sb->s_fs_info = NULL;	kfree(sbi);}static int fat_show_options(struct seq_file *m, struct vfsmount *mnt){	struct msdos_sb_info *sbi = MSDOS_SB(mnt->mnt_sb);	struct fat_mount_options *opts = &sbi->options;	int isvfat = opts->isvfat;	if (opts->fs_uid != 0)		seq_printf(m, ",uid=%u", opts->fs_uid);	if (opts->fs_gid != 0)		seq_printf(m, ",gid=%u", opts->fs_gid);	seq_printf(m, ",fmask=%04o", opts->fs_fmask);	seq_printf(m, ",dmask=%04o", opts->fs_dmask);	if (sbi->nls_disk && opts->codepage != fat_default_codepage)		seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);	if (isvfat) {		if (sbi->nls_io &&		    strcmp(opts->iocharset, fat_default_iocharset))			seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);		switch (opts->shortname) {		case VFAT_SFN_DISPLAY_WIN95 | VFAT_SFN_CREATE_WIN95:			seq_puts(m, ",shortname=win95");			break;		case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WINNT:			seq_puts(m, ",shortname=winnt");			break;		case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WIN95:			seq_puts(m, ",shortname=mixed");			break;		case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95:			/* seq_puts(m, ",shortname=lower"); */			break;		default:			seq_puts(m, ",shortname=unknown");			break;		}	}	if (opts->name_check != 'n')		seq_printf(m, ",check=%c", opts->name_check);	if (opts->quiet)		seq_puts(m, ",quiet");	if (opts->showexec)		seq_puts(m, ",showexec");	if (opts->sys_immutable)		seq_puts(m, ",sys_immutable");	if (!isvfat) {		if (opts->dotsOK)			seq_puts(m, ",dotsOK=yes");		if (opts->nocase)			seq_puts(m, ",nocase");	} else {		if (opts->utf8)			seq_puts(m, ",utf8");		if (opts->unicode_xlate)			seq_puts(m, ",uni_xlate");		if (!opts->numtail)			seq_puts(m, ",nonumtail");	}	return 0;}enum {	Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,	Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_nocase,	Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable,	Opt_dots, Opt_nodots,	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,	Opt_obsolate, Opt_err,};static match_table_t fat_tokens = {	{Opt_check_r, "check=relaxed"},	{Opt_check_s, "check=strict"},	{Opt_check_n, "check=normal"},	{Opt_check_r, "check=r"},	{Opt_check_s, "check=s"},	{Opt_check_n, "check=n"},	{Opt_uid, "uid=%u"},	{Opt_gid, "gid=%u"},	{Opt_umask, "umask=%o"},	{Opt_dmask, "dmask=%o"},	{Opt_fmask, "fmask=%o"},	{Opt_codepage, "codepage=%u"},	{Opt_nocase, "nocase"},	{Opt_quiet, "quiet"},	{Opt_showexec, "showexec"},	{Opt_debug, "debug"},	{Opt_immutable, "sys_immutable"},	{Opt_obsolate, "conv=binary"},	{Opt_obsolate, "conv=text"},	{Opt_obsolate, "conv=auto"},	{Opt_obsolate, "conv=b"},	{Opt_obsolate, "conv=t"},	{Opt_obsolate, "conv=a"},	{Opt_obsolate, "fat=%u"},	{Opt_obsolate, "blocksize=%u"},	{Opt_obsolate, "cvf_format=%20s"},	{Opt_obsolate, "cvf_options=%100s"},	{Opt_obsolate, "posix"},	{Opt_err, NULL}};static match_table_t msdos_tokens = {	{Opt_nodots, "nodots"},	{Opt_nodots, "dotsOK=no"},	{Opt_dots, "dots"},	{Opt_dots, "dotsOK=yes"},	{Opt_err, NULL}};static match_table_t vfat_tokens = {	{Opt_charset, "iocharset=%s"},	{Opt_shortname_lower, "shortname=lower"},	{Opt_shortname_win95, "shortname=win95"},	{Opt_shortname_winnt, "shortname=winnt"},	{Opt_shortname_mixed, "shortname=mixed"},	{Opt_utf8_no, "utf8=0"},		/* 0 or no or false */	{Opt_utf8_no, "utf8=no"},	{Opt_utf8_no, "utf8=false"},	{Opt_utf8_yes, "utf8=1"},		/* empty or 1 or yes or true */	{Opt_utf8_yes, "utf8=yes"},	{Opt_utf8_yes, "utf8=true"},	{Opt_utf8_yes, "utf8"},	{Opt_uni_xl_no, "uni_xlate=0"},		/* 0 or no or false */	{Opt_uni_xl_no, "uni_xlate=no"},	{Opt_uni_xl_no, "uni_xlate=false"},	{Opt_uni_xl_yes, "uni_xlate=1"},	/* empty or 1 or yes or true */	{Opt_uni_xl_yes, "uni_xlate=yes"},	{Opt_uni_xl_yes, "uni_xlate=true"},	{Opt_uni_xl_yes, "uni_xlate"},	{Opt_nonumtail_no, "nonumtail=0"},	/* 0 or no or false */	{Opt_nonumtail_no, "nonumtail=no"},	{Opt_nonumtail_no, "nonumtail=false"},	{Opt_nonumtail_yes, "nonumtail=1"},	/* empty or 1 or yes or true */	{Opt_nonumtail_yes, "nonumtail=yes"},	{Opt_nonumtail_yes, "nonumtail=true"},	{Opt_nonumtail_yes, "nonumtail"},	{Opt_err, NULL}};static int parse_options(char *options, int is_vfat, int *debug,			 struct fat_mount_options *opts){	char *p;	substring_t args[MAX_OPT_ARGS];	int option;	char *iocharset;	opts->isvfat = is_vfat;	opts->fs_uid = current->uid;	opts->fs_gid = current->gid;	opts->fs_fmask = opts->fs_dmask = current->fs->umask;	opts->codepage = fat_default_codepage;	opts->iocharset = fat_default_iocharset;	if (is_vfat)		opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;	else		opts->shortname = 0;	opts->name_check = 'n';	opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK =  0;	opts->utf8 = opts->unicode_xlate = 0;	opts->numtail = 1;	opts->nocase = 0;	*debug = 0;	if (!options)		return 0;	while ((p = strsep(&options, ",")) != NULL) {		int token;		if (!*p)			continue;		token = match_token(p, fat_tokens, args);		if (token == Opt_err) {			if (is_vfat)				token = match_token(p, vfat_tokens, args);			else				token = match_token(p, msdos_tokens, args);		}		switch (token) {		case Opt_check_s:			opts->name_check = 's';			break;		case Opt_check_r:			opts->name_check = 'r';			break;		case Opt_check_n:			opts->name_check = 'n';			break;		case Opt_nocase:			if (!is_vfat)				opts->nocase = 1;			else {				/* for backward compatibility */				opts->shortname = VFAT_SFN_DISPLAY_WIN95					| VFAT_SFN_CREATE_WIN95;			}			break;		case Opt_quiet:			opts->quiet = 1;			break;		case Opt_showexec:			opts->showexec = 1;			break;		case Opt_debug:			*debug = 1;			break;		case Opt_immutable:			opts->sys_immutable = 1;			break;		case Opt_uid:			if (match_int(&args[0], &option))				return 0;			opts->fs_uid = option;			break;		case Opt_gid:			if (match_int(&args[0], &option))				return 0;			opts->fs_gid = option;			break;		case Opt_umask:			if (match_octal(&args[0], &option))				return 0;			opts->fs_fmask = opts->fs_dmask = option;			break;		case Opt_dmask:			if (match_octal(&args[0], &option))				return 0;			opts->fs_dmask = option;			break;		case Opt_fmask:			if (match_octal(&args[0], &option))				return 0;			opts->fs_fmask = option;			break;		case Opt_codepage:			if (match_int(&args[0], &option))				return 0;			opts->codepage = option;			break;		/* msdos specific */		case Opt_dots:			opts->dotsOK = 1;			break;		case Opt_nodots:			opts->dotsOK = 0;			break;		/* vfat specific */		case Opt_charset:

⌨️ 快捷键说明

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