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

📄 inode.c

📁 linux环境下基于FAT的文件系统的通用代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static void __exit fat_destroy_inodecache(void){	kmem_cache_destroy(fat_inode_cachep);}static int fat_remount(struct super_block *sb, int *flags, char *data){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	*flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);	return 0;}static int fat_statfs(struct dentry *dentry, struct kstatfs *buf){	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);	/* If the count of free cluster is still unknown, counts it here. */	if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {		int err = fat_count_free_clusters(dentry->d_sb);		if (err)			return err;	}	buf->f_type = dentry->d_sb->s_magic;	buf->f_bsize = sbi->cluster_size;	buf->f_blocks = sbi->max_cluster - FAT_START_ENT;	buf->f_bfree = sbi->free_clusters;	buf->f_bavail = sbi->free_clusters;	buf->f_namelen = sbi->options.isvfat ? 260 : 12;	return 0;}static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,				    struct inode *inode){	loff_t i_pos;#if BITS_PER_LONG == 32	spin_lock(&sbi->inode_hash_lock);#endif	i_pos = MSDOS_I(inode)->i_pos;#if BITS_PER_LONG == 32	spin_unlock(&sbi->inode_hash_lock);#endif	return i_pos;}static int fat_write_inode(struct inode *inode, int wait){	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct buffer_head *bh;	struct msdos_dir_entry *raw_entry;	loff_t i_pos;	int err;	if (inode->i_ino == MSDOS_ROOT_INO)		return 0;retry:	i_pos = fat_i_pos_read(sbi, inode);	if (!i_pos)		return 0;	bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);	if (!bh) {		printk(KERN_ERR "FAT: unable to read inode block "		       "for updating (i_pos %lld)\n", i_pos);		return -EIO;	}	spin_lock(&sbi->inode_hash_lock);	if (i_pos != MSDOS_I(inode)->i_pos) {		spin_unlock(&sbi->inode_hash_lock);		brelse(bh);		goto retry;	}	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))	    [i_pos & (sbi->dir_per_block - 1)];	if (S_ISDIR(inode->i_mode))		raw_entry->size = 0;	else		raw_entry->size = cpu_to_le32(inode->i_size);	raw_entry->attr = fat_make_attrs(inode);	raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);	raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);	fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,			  &raw_entry->date, NULL);	if (sbi->options.isvfat) {		__le16 atime;		fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,				  &raw_entry->cdate, &raw_entry->ctime_cs);		fat_time_unix2fat(sbi, &inode->i_atime, &atime,				  &raw_entry->adate, NULL);	}	spin_unlock(&sbi->inode_hash_lock);	mark_buffer_dirty(bh);	err = 0;	if (wait)		err = sync_dirty_buffer(bh);	brelse(bh);	return err;}int fat_sync_inode(struct inode *inode){	return fat_write_inode(inode, 1);}EXPORT_SYMBOL_GPL(fat_sync_inode);static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);static const 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,	.write_super	= fat_write_super,	.statfs		= fat_statfs,	.clear_inode	= fat_clear_inode,	.remount_fs	= fat_remount,	.show_options	= fat_show_options,};/* * 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_fh_to_dentry(struct super_block *sb,		struct fid *fid, int fh_len, int fh_type){	struct inode *inode = NULL;	struct dentry *result;	u32 *fh = fid->raw;	if (fh_len < 5 || fh_type != 3)		return NULL;	inode = ilookup(sb, fh[0]);	if (!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;		}	}	/*	 * For now, do nothing if the inode is not found.	 *	 * What we could do is:	 *	 *	- follow the file starting at fh[4], and record the ".." entry,	 *	  and the name of the fh[2] entry.	 *	- then 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 we are totally out	 * of luck.  But all that is for another day	 */	result = d_obtain_alias(inode);	if (!IS_ERR(result))		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 super_block *sb = child->d_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de;	loff_t i_pos;	struct dentry *parent;	struct inode *inode;	int err;	lock_super(sb);	err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);	if (err) {		parent = ERR_PTR(err);		goto out;	}	inode = fat_build_inode(sb, de, i_pos);	brelse(bh);	parent = d_obtain_alias(inode);	if (!IS_ERR(parent))		parent->d_op = sb->s_root->d_op;out:	unlock_super(sb);	return parent;}static const struct export_operations fat_export_ops = {	.encode_fh	= fat_encode_fh,	.fh_to_dentry	= fat_fh_to_dentry,	.get_parent	= fat_get_parent,};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 (opts->allow_utime)		seq_printf(m, ",allow_utime=%04o", opts->allow_utime);	if (sbi->nls_disk)		seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);	if (isvfat) {		if (sbi->nls_io)			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->usefree)		seq_puts(m, ",usefree");	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");		if (opts->rodir)			seq_puts(m, ",rodir");	}	if (opts->flush)		seq_puts(m, ",flush");	if (opts->tz_utc)		seq_puts(m, ",tz=UTC");	return 0;}enum {	Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,	Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,	Opt_usefree, 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_flush, Opt_tz_utc, Opt_rodir, Opt_err,};static const 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_allow_utime, "allow_utime=%o"},	{Opt_codepage, "codepage=%u"},	{Opt_usefree, "usefree"},	{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_flush, "flush"},	{Opt_tz_utc, "tz=UTC"},	{Opt_err, NULL},};static const match_table_t msdos_tokens = {	{Opt_nodots, "nodots"},	{Opt_nodots, "dotsOK=no"},	{Opt_dots, "dots"},	{Opt_dots, "dotsOK=yes"},	{Opt_err, NULL}};static const 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_rodir, "rodir"},	{Opt_err, NULL}};static int parse_options(char *options, int is_vfat, int silent, 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->allow_utime = -1;	opts->codepage = fat_default_codepage;	opts->iocharset = fat_default_iocharset;	if (is_vfat) {		opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;		opts->rodir = 0;	} else {		opts->shortname = 0;		opts->rodir = 1;	}	opts->name_check = 'n';	opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK =  0;	opts->utf8 = opts->unicode_xlate = 0;	opts->numtail = 1;	opts->usefree = opts->nocase = 0;	opts->tz_utc = 0;	*debug = 0;	if (!options)		goto out;	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_usefree:			opts->usefree = 1;			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))

⌨️ 快捷键说明

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