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

📄 inode.c

📁 linux环境下基于FAT的文件系统的通用代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				return 0;			opts->fs_fmask = option;			break;		case Opt_allow_utime:			if (match_octal(&args[0], &option))				return 0;			opts->allow_utime = option & (S_IWGRP | S_IWOTH);			break;		case Opt_codepage:			if (match_int(&args[0], &option))				return 0;			opts->codepage = option;			break;		case Opt_flush:			opts->flush = 1;			break;		case Opt_tz_utc:			opts->tz_utc = 1;			break;		/* msdos specific */		case Opt_dots:			opts->dotsOK = 1;			break;		case Opt_nodots:			opts->dotsOK = 0;			break;		/* vfat specific */		case Opt_charset:			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;		case Opt_rodir:			opts->rodir = 1;			break;		/* obsolete mount options */		case Opt_obsolate:			printk(KERN_INFO "FAT: \"%s\" option is obsolete, "			       "not supported now\n", p);			break;		/* unknown option */		default:			if (!silent) {				printk(KERN_ERR				       "FAT: Unrecognized mount option \"%s\" "				       "or missing value\n", p);			}			return -EINVAL;		}	}out:	/* UTF-8 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 user doesn't specify allow_utime, it's initialized from dmask. */	if (opts->allow_utime == (unsigned short)-1)		opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);	if (opts->unicode_xlate)		opts->utf8 = 0;	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)->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 = fat_make_mode(sbi, ATTR_DIR, S_IRWXUGO);	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_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;	fat_save_attrs(inode, ATTR_DIR);	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;	inode->i_nlink = fat_subdirs(inode)+2;	return 0;}/* * Read the super block of an MS-DOS FS. */int fat_fill_super(struct super_block *sb, void *data, int silent,		   const 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;	unsigned int media;	long error;	char buf[50];	/*	 * GFP_KERNEL is ok here, because while we do hold the	 * supeblock lock, memory pressure can't call back into	 * the filesystem, since we're only just about to mount	 * it and have no inodes etc active!	 */	sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);	if (!sbi)		return -ENOMEM;	sb->s_fs_info = sbi;	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, silent, &debug, &sbi->options);	if (error)		goto out_fail;	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 = get_unaligned_le16(&b->sector_size);	if (!is_power_of_2(logical_sector_size)	    || (logical_sector_size < 512)	    || (logical_sector_size > 4096)) {		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 (!is_power_of_2(sbi->sec_per_clus)) {		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)) {			printk(KERN_ERR "FAT: unable to set blocksize %u\n",			       logical_sector_size);			goto out_fail;		}		bh = sb_bread(sb, 0);		if (bh == NULL) {			printk(KERN_ERR "FAT: unable to read boot sector"			       " (logical sector size = %lu)\n",			       sb->s_blocksize);			goto out_fail;		}		b = (struct fat_boot_sector *) bh->b_data;	}	sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus;	sbi->cluster_bits = ffs(sbi->cluster_size) - 1;	sbi->fats = b->fats;	sbi->fat_bits = 0;		/* Don't know yet */	sbi->fat_start = le16_to_cpu(b->reserved);	sbi->fat_length = le16_to_cpu(b->fat_length);	sbi->root_cluster = 0;	sbi->free_clusters = -1;	/* Don't know yet */	sbi->free_clus_valid = 0;	sbi->prev_free = FAT_START_ENT;	if (!sbi->fat_length && b->fat32_length) {		struct fat_boot_fsinfo *fsinfo;		struct buffer_head *fsinfo_bh;		/* Must be FAT32 */		sbi->fat_bits = 32;		sbi->fat_length = le32_to_cpu(b->fat32_length);		sbi->root_cluster = le32_to_cpu(b->root_cluster);		sb->s_maxbytes = 0xffffffff;		/* MC - if info_sector is 0, don't multiply by 0 */		sbi->fsinfo_sector = le16_to_cpu(b->info_sector);		if (sbi->fsinfo_sector == 0)			sbi->fsinfo_sector = 1;		fsinfo_bh = sb_bread(sb, sbi->fsinfo_sector);		if (fsinfo_bh == NULL) {			printk(KERN_ERR "FAT: bread failed, FSINFO block"			       " (sector = %lu)\n", sbi->fsinfo_sector);			brelse(bh);			goto out_fail;		}		fsinfo = (struct fat_boot_fsinfo *)fsinfo_bh->b_data;		if (!IS_FSINFO(fsinfo)) {			printk(KERN_WARNING "FAT: Invalid FSINFO signature: "			       "0x%08x, 0x%08x (sector = %lu)\n",			       le32_to_cpu(fsinfo->signature1),			       le32_to_cpu(fsinfo->signature2),			       sbi->fsinfo_sector);		} else {			if (sbi->options.usefree)				sbi->free_clus_valid = 1;			sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters);			sbi->prev_free = le32_to_cpu(fsinfo->next_cluster);		}		brelse(fsinfo_bh);	}	sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;	sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;	sbi->dir_entries = get_unaligned_le16(&b->dir_entries);	if (sbi->dir_entries & (sbi->dir_per_block - 1)) {		if (!silent)			printk(KERN_ERR "FAT: bogus directroy-entries per block"			       " (%u)\n", sbi->dir_entries);		brelse(bh);		goto out_invalid;	}	rootdir_sectors = sbi->dir_entries		* sizeof(struct msdos_dir_entry) / sb->s_blocksize;	sbi->data_start = sbi->dir_start + rootdir_sectors;	total_sectors = get_unaligned_le16(&b->sectors);	if (total_sectors == 0)		total_sectors = le32_to_cpu(b->total_sect);	total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;	if (sbi->fat_bits != 32)		sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;	/* check that FAT table does not overflow */	fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;	total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT);	if (total_clusters > MAX_FAT(sb)) {		if (!silent)			printk(KERN_ERR "FAT: count of clusters too big (%u)\n",			       total_clusters);		brelse(bh);		goto out_invalid;	}	sbi->max_cluster = total_clusters + FAT_START_ENT;	/* check the free_clusters, it's not necessarily correct */	if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters)		sbi->free_clusters = -1;	/* check the prev_free, it's not necessarily correct */	sbi->prev_free %= sbi->max_cluster;	if (sbi->prev_free < FAT_START_ENT)		sbi->prev_free = FAT_START_ENT;	brelse(bh);	/* set up enough so that it can read an inode */	fat_hash_init(sb);	fat_ent_access_init(sb);	/*	 * The low byte of FAT's first entry must have same value with	 * media-field.  But in real world, too many devices is	 * writing wrong value.  So, removed that validity check.	 *	 * if (FAT_FIRST_ENT(sb, media) != first)	 */	error = -EINVAL;	sprintf(buf, "cp%d", sbi->options.codepage);	sbi->nls_disk = load_nls(buf);	if (!sbi->nls_disk) {		printk(KERN_ERR "FAT: codepage %s not found\n", buf);		goto out_fail;	}	/* FIXME: utf8 is using iocharset for upper/lower conversion */	if (sbi->options.isvfat) {		sbi->nls_io = load_nls(sbi->options.iocharset);		if (!sbi->nls_io) {			printk(KERN_ERR "FAT: IO charset %s not found\n",			       sbi->options.iocharset);			goto out_fail;		}	}	error = -ENOMEM;	root_inode = new_inode(sb);	if (!root_inode)		goto out_fail;	root_inode->i_ino = MSDOS_ROOT_INO;	root_inode->i_version = 1;	error = fat_read_root(root_inode);	if (error < 0)		goto out_fail;	error = -ENOMEM;	insert_inode_hash(root_inode);	sb->s_root = d_alloc_root(root_inode);	if (!sb->s_root) {		printk(KERN_ERR "FAT: get root inode failed\n");		goto out_fail;	}	return 0;out_invalid:	error = -EINVAL;	if (!silent)		printk(KERN_INFO "VFS: Can't find a valid FAT filesystem"		       " on dev %s.\n", sb->s_id);out_fail:	if (root_inode)		iput(root_inode);	if (sbi->nls_io)		unload_nls(sbi->nls_io);	if (sbi->nls_disk)		unload_nls(sbi->nls_disk);	if (sbi->options.iocharset != fat_default_iocharset)		kfree(sbi->options.iocharset);	sb->s_fs_info = NULL;	kfree(sbi);	return error;}EXPORT_SYMBOL_GPL(fat_fill_super);/* * helper function for fat_flush_inodes.  This writes both the inode * and the file data blocks, waiting for in flight data blocks before * the start of the call.  It does not wait for any io started * during the call */static int writeback_inode(struct inode *inode){	int ret;	struct address_space *mapping = inode->i_mapping;	struct writeback_control wbc = {	       .sync_mode = WB_SYNC_NONE,	      .nr_to_write = 0,	};	/* if we used WB_SYNC_ALL, sync_inode waits for the io for the	* inode to finish.  So WB_SYNC_NONE is sent down to sync_inode	* and filemap_fdatawrite is used for the data blocks	*/	ret = sync_inode(inode, &wbc);	if (!ret)	       ret = filemap_fdatawrite(mapping);	return ret;}/* * write data and metadata corresponding to i1 and i2.  The io is * started but we do not wait for any of it to finish. * * filemap_flush is used for the block device, so if there is a dirty * page for a block already in flight, we will not wait and start the * io over again */int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2){	int ret = 0;	if (!MSDOS_SB(sb)->options.flush)		return 0;	if (i1)		ret = writeback_inode(i1);	if (!ret && i2)		ret = writeback_inode(i2);	if (!ret) {		struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;		ret = filemap_flush(mapping);	}	return ret;}EXPORT_SYMBOL_GPL(fat_flush_inodes);static int __init init_fat_fs(void){	int err;	err = fat_cache_init();	if (err)		return err;	err = fat_init_inodecache();	if (err)		goto failed;	return 0;failed:	fat_cache_destroy();	return err;}static void __exit exit_fat_fs(void){	fat_cache_destroy();	fat_destroy_inodecache();}module_init(init_fat_fs)module_exit(exit_fat_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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