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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (opts->iocharset != fat_default_iocharset)				kfree(opts->iocharset);			iocharset = match_strdup(&args[0]);			if (!iocharset)				return -ENOMEM;			opts->iocharset = iocharset;			break;		case Opt_shortname_lower:			opts->shortname = VFAT_SFN_DISPLAY_LOWER					| VFAT_SFN_CREATE_WIN95;			break;		case Opt_shortname_win95:			opts->shortname = VFAT_SFN_DISPLAY_WIN95					| VFAT_SFN_CREATE_WIN95;			break;		case Opt_shortname_winnt:			opts->shortname = VFAT_SFN_DISPLAY_WINNT					| VFAT_SFN_CREATE_WINNT;			break;		case Opt_shortname_mixed:			opts->shortname = VFAT_SFN_DISPLAY_WINNT					| VFAT_SFN_CREATE_WIN95;			break;		case Opt_utf8_no:		/* 0 or no or false */			opts->utf8 = 0;			break;		case Opt_utf8_yes:		/* empty or 1 or yes or true */			opts->utf8 = 1;			break;		case Opt_uni_xl_no:		/* 0 or no or false */			opts->unicode_xlate = 0;			break;		case Opt_uni_xl_yes:		/* empty or 1 or yes or true */			opts->unicode_xlate = 1;			break;		case Opt_nonumtail_no:		/* 0 or no or false */			opts->numtail = 1;	/* negated option */			break;		case Opt_nonumtail_yes:		/* empty or 1 or yes or true */			opts->numtail = 0;	/* negated option */			break;		/* obsolete mount options */		case Opt_obsolate:			printk(KERN_INFO "FAT: \"%s\" option is obsolete, "			       "not supported now\n", p);			break;		/* unknown option */		default:			printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" "			       "or missing value\n", p);			return -EINVAL;		}	}	/* UTF8 doesn't provide FAT semantics */	if (!strcmp(opts->iocharset, "utf8")) {		printk(KERN_ERR "FAT: utf8 is not a recommended IO charset"		       " for FAT filesystems, filesystem will be case sensitive!\n");	}	if (opts->unicode_xlate)		opts->utf8 = 0;		return 0;}static int fat_calc_dir_size(struct inode *inode){	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);	int ret, fclus, dclus;	inode->i_size = 0;	if (MSDOS_I(inode)->i_start == 0)		return 0;	ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);	if (ret < 0)		return ret;	inode->i_size = (fclus + 1) << sbi->cluster_bits;	return 0;}static int fat_read_root(struct inode *inode){	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	int error;	MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;	MSDOS_I(inode)->i_pos = 0;	inode->i_uid = sbi->options.fs_uid;	inode->i_gid = sbi->options.fs_gid;	inode->i_version++;	inode->i_generation = 0;	inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR;	inode->i_op = sbi->dir_ops;	inode->i_fop = &fat_dir_operations;	if (sbi->fat_bits == 32) {		MSDOS_I(inode)->i_start = sbi->root_cluster;		error = fat_calc_dir_size(inode);		if (error < 0)			return error;	} else {		MSDOS_I(inode)->i_start = 0;		inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);	}	inode->i_blksize = sbi->cluster_size;	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;	MSDOS_I(inode)->i_logstart = 0;	MSDOS_I(inode)->mmu_private = inode->i_size;	MSDOS_I(inode)->i_attrs = 0;	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;	MSDOS_I(inode)->i_ctime_ms = 0;	inode->i_nlink = fat_subdirs(inode)+2;	return 0;}/* * a FAT file handle with fhtype 3 is *  0/  i_ino - for fast, reliable lookup if still in the cache *  1/  i_generation - to see if i_ino is still valid *          bit 0 == 0 iff directory *  2/  i_pos(8-39) - if ino has changed, but still in cache *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc * * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits * of i_logstart is used to store the directory entry offset. */static struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, 	      int (*acceptable)(void *context, struct dentry *de),	      void *context){	if (fhtype != 3)		return ERR_PTR(-ESTALE);	if (len < 5)		return ERR_PTR(-ESTALE);	return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);}static struct dentry *fat_get_dentry(struct super_block *sb, void *inump){	struct inode *inode = NULL;	struct dentry *result;	__u32 *fh = inump;	inode = iget(sb, fh[0]);	if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {		if (inode)			iput(inode);		inode = NULL;	}	if (!inode) {		loff_t i_pos;		int i_logstart = fh[3] & 0x0fffffff;		i_pos = (loff_t)fh[2] << 8;		i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);		/* try 2 - see if i_pos is in F-d-c		 * require i_logstart to be the same		 * Will fail if you truncate and then re-write		 */		inode = fat_iget(sb, i_pos);		if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {			iput(inode);			inode = NULL;		}	}	if (!inode) {		/* For now, do nothing		 * What we could do is:		 * follow the file starting at fh[4], and record		 * the ".." entry, and the name of the fh[2] entry.		 * The follow the ".." file finding the next step up.		 * This way we build a path to the root of		 * the tree. If this works, we lookup the path and so		 * get this inode into the cache.		 * Finally try the fat_iget lookup again		 * If that fails, then weare totally out of luck		 * But all that is for another day		 */	}	if (!inode)		return ERR_PTR(-ESTALE);		/* now to find a dentry.	 * If possible, get a well-connected one	 */	result = d_alloc_anon(inode);	if (result == NULL) {		iput(inode);		return ERR_PTR(-ENOMEM);	}	result->d_op = sb->s_root->d_op;	return result;}static intfat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable){	int len = *lenp;	struct inode *inode =  de->d_inode;	u32 ipos_h, ipos_m, ipos_l;		if (len < 5)		return 255; /* no room */	ipos_h = MSDOS_I(inode)->i_pos >> 8;	ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;	ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;	*lenp = 5;	fh[0] = inode->i_ino;	fh[1] = inode->i_generation;	fh[2] = ipos_h;	fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;	spin_lock(&de->d_lock);	fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;	spin_unlock(&de->d_lock);	return 3;}static struct dentry *fat_get_parent(struct dentry *child){	struct buffer_head *bh=NULL;	struct msdos_dir_entry *de = NULL;	struct dentry *parent = NULL;	int res;	loff_t i_pos = 0;	struct inode *inode;	lock_kernel();	res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);	if (res < 0)		goto out;	inode = fat_build_inode(child->d_sb, de, i_pos, &res);	if (res)		goto out;	if (!inode)		res = -EACCES;	else {		parent = d_alloc_anon(inode);		if (!parent) {			iput(inode);			res = -ENOMEM;		}	} out:	if(bh)		brelse(bh);	unlock_kernel();	if (res)		return ERR_PTR(res);	else		return parent;}static kmem_cache_t *fat_inode_cachep;static struct inode *fat_alloc_inode(struct super_block *sb){	struct msdos_inode_info *ei;	ei = (struct msdos_inode_info *)kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL);	if (!ei)		return NULL;	return &ei->vfs_inode;}static void fat_destroy_inode(struct inode *inode){	kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));}static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags){	struct msdos_inode_info *ei = (struct msdos_inode_info *) foo;	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==	    SLAB_CTOR_CONSTRUCTOR) {		INIT_LIST_HEAD(&ei->i_fat_hash);		inode_init_once(&ei->vfs_inode);	}} int __init fat_init_inodecache(void){	fat_inode_cachep = kmem_cache_create("fat_inode_cache",					     sizeof(struct msdos_inode_info),					     0, SLAB_RECLAIM_ACCOUNT,					     init_once, NULL);	if (fat_inode_cachep == NULL)		return -ENOMEM;	return 0;}void __exit fat_destroy_inodecache(void){	if (kmem_cache_destroy(fat_inode_cachep))		printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");}static int fat_remount(struct super_block *sb, int *flags, char *data){	*flags |= MS_NODIRATIME;	return 0;}static struct super_operations fat_sops = { 	.alloc_inode	= fat_alloc_inode,	.destroy_inode	= fat_destroy_inode,	.write_inode	= fat_write_inode,	.delete_inode	= fat_delete_inode,	.put_super	= fat_put_super,	.statfs		= fat_statfs,	.clear_inode	= fat_clear_inode,	.remount_fs	= fat_remount,	.read_inode	= make_bad_inode,	.show_options	= fat_show_options,};static struct export_operations fat_export_ops = {	.decode_fh	= fat_decode_fh,	.encode_fh	= fat_encode_fh,	.get_dentry	= fat_get_dentry,	.get_parent	= fat_get_parent,};/* * Read the super block of an MS-DOS FS. */int fat_fill_super(struct super_block *sb, void *data, int silent,		   struct inode_operations *fs_dir_inode_ops, int isvfat){	struct inode *root_inode = NULL;	struct buffer_head *bh;	struct fat_boot_sector *b;	struct msdos_sb_info *sbi;	u16 logical_sector_size;	u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;	int debug, first;	unsigned int media;	long error;	char buf[50];	sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);	if (!sbi)		return -ENOMEM;	sb->s_fs_info = sbi;	memset(sbi, 0, sizeof(struct msdos_sb_info));	sb->s_flags |= MS_NODIRATIME;	sb->s_magic = MSDOS_SUPER_MAGIC;	sb->s_op = &fat_sops;	sb->s_export_op = &fat_export_ops;	sbi->dir_ops = fs_dir_inode_ops;	error = parse_options(data, isvfat, &debug, &sbi->options);	if (error)		goto out_fail;	fat_cache_init(sb);	/* set up enough so that it can read an inode */	init_MUTEX(&sbi->fat_lock);	error = -EIO;	sb_min_blocksize(sb, 512);	bh = sb_bread(sb, 0);	if (bh == NULL) {		printk(KERN_ERR "FAT: unable to read boot sector\n");		goto out_fail;	}	b = (struct fat_boot_sector *) bh->b_data;	if (!b->reserved) {		if (!silent)			printk(KERN_ERR "FAT: bogus number of reserved sectors\n");		brelse(bh);		goto out_invalid;	}	if (!b->fats) {		if (!silent)			printk(KERN_ERR "FAT: bogus number of FAT structure\n");		brelse(bh);		goto out_invalid;	}	/*	 * Earlier we checked here that b->secs_track and b->head are nonzero,	 * but it turns out valid FAT filesystems can have zero there.	 */	media = b->media;	if (!FAT_VALID_MEDIA(media)) {		if (!silent)			printk(KERN_ERR "FAT: invalid media value (0x%02x)\n",			       media);		brelse(bh);		goto out_invalid;	}	logical_sector_size = CF_LE_W(get_unaligned((__le16 *)&b->sector_size));	if (!logical_sector_size	    || (logical_sector_size & (logical_sector_size - 1))	    || (logical_sector_size < 512)	    || (PAGE_CACHE_SIZE < logical_sector_size)) {		if (!silent)			printk(KERN_ERR "FAT: bogus logical sector size %u\n",			       logical_sector_size);		brelse(bh);		goto out_invalid;	}	sbi->sec_per_clus = b->sec_per_clus;	if (!sbi->sec_per_clus	    || (sbi->sec_per_clus & (sbi->sec_per_clus - 1))) {		if (!silent)			printk(KERN_ERR "FAT: bogus sectors per cluster %u\n",			       sbi->sec_per_clus);		brelse(bh);		goto out_invalid;	}	if (logical_sector_size < sb->s_blocksize) {		printk(KERN_ERR "FAT: logical sector size too small for device"		       " (logical sector size = %u)\n", logical_sector_size);		brelse(bh);		goto out_fail;	}	if (logical_sector_size > sb->s_blocksize) {		brelse(bh);		if (!sb_set_blocksize(sb, logical_sector_size)) {

⌨️ 快捷键说明

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