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

📄 inode.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
	read_inode:	make_bad_inode,	fh_to_dentry:	fat_fh_to_dentry,	dentry_to_fh:	fat_dentry_to_fh,};/* * Read the super block of an MS-DOS FS. * * Note that this may be called from vfat_read_super * with some fields already initialized. */struct super_block *fat_read_super(struct super_block *sb, void *data, int silent,		struct inode_operations *fs_dir_inode_ops){	struct inode *root_inode;	struct buffer_head *bh;	struct fat_boot_sector *b;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	char *p;	int logical_sector_size, hard_blksize, fat_clusters = 0;	unsigned int total_sectors, rootdir_sectors;	int fat32, debug, error, fat, cp;	struct fat_mount_options opts;	char buf[50];	int i;	char cvf_format[21];	char cvf_options[101];	cvf_format[0] = '\0';	cvf_options[0] = '\0';	sbi->cvf_format = NULL;	sbi->private_data = NULL;	sbi->dir_ops = fs_dir_inode_ops;	sb->s_maxbytes = MAX_NON_LFS;	sb->s_op = &fat_sops;	hard_blksize = get_hardsect_size(sb->s_dev);	if (!hard_blksize)		hard_blksize = 512;	opts.isvfat = sbi->options.isvfat;	if (!parse_options((char *) data, &fat, &debug, &opts,			   cvf_format, cvf_options))		goto out_fail;	/* N.B. we should parse directly into the sb structure */	memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));	fat_cache_init();	sb->s_blocksize = hard_blksize;	set_blocksize(sb->s_dev, hard_blksize);	bh = sb_bread(sb, 0);	if (bh == NULL) {		printk("FAT: unable to read boot sector\n");		goto out_fail;	}/* * The DOS3 partition size limit is *not* 32M as many people think.   * Instead, it is 64K sectors (with the usual sector size being * 512 bytes, leading to a 32M limit). *  * DOS 3 partition managers got around this problem by faking a  * larger sector size, ie treating multiple physical sectors as  * a single logical sector. *  * We can accommodate this scheme by adjusting our cluster size, * fat_start, and data_start by an appropriate value. * * (by Drew Eckhardt) */	b = (struct fat_boot_sector *) bh->b_data;	logical_sector_size =		CF_LE_W(get_unaligned((unsigned short *) &b->sector_size));	if (!logical_sector_size	    || (logical_sector_size & (logical_sector_size - 1))) {		printk("FAT: bogus logical sector size %d\n",		       logical_sector_size);		brelse(bh);		goto out_invalid;	}	sbi->cluster_size = b->cluster_size;	if (!sbi->cluster_size	    || (sbi->cluster_size & (sbi->cluster_size - 1))) {		printk("FAT: bogus cluster size %d\n", sbi->cluster_size);		brelse(bh);		goto out_invalid;	}	if (logical_sector_size < hard_blksize) {		printk("FAT: logical sector size too small for device"		       " (logical sector size = %d)\n", logical_sector_size);		brelse(bh);		goto out_invalid;	}	sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1;	sbi->fats = b->fats;	sbi->fat_start = CF_LE_W(b->reserved);	if (!b->fat_length && b->fat32_length) {		struct fat_boot_fsinfo *fsinfo;		struct buffer_head *fsinfo_bh;		int fsinfo_block, fsinfo_offset;		/* Must be FAT32 */		fat32 = 1;		sbi->fat_length = CF_LE_L(b->fat32_length);		sbi->root_cluster = CF_LE_L(b->root_cluster);		sbi->fsinfo_sector = CF_LE_W(b->info_sector);		/* MC - if info_sector is 0, don't multiply by 0 */		if (sbi->fsinfo_sector == 0)			sbi->fsinfo_sector = 1;		fsinfo_block =			(sbi->fsinfo_sector * logical_sector_size) / hard_blksize;		fsinfo_offset =			(sbi->fsinfo_sector * logical_sector_size) % hard_blksize;		fsinfo_bh = bh;		if (fsinfo_block != 0) {			fsinfo_bh = sb_bread(sb, fsinfo_block);			if (fsinfo_bh == NULL) {				printk("FAT: bread failed, FSINFO block"				       " (blocknr = %d)\n", fsinfo_block);				brelse(bh);				goto out_invalid;			}		}		fsinfo = (struct fat_boot_fsinfo *)&fsinfo_bh->b_data[fsinfo_offset];		if (!IS_FSINFO(fsinfo)) {			printk("FAT: Did not find valid FSINFO signature.\n"			       "Found signature1 0x%x signature2 0x%x sector=%ld.\n",			       CF_LE_L(fsinfo->signature1),			       CF_LE_L(fsinfo->signature2),			       sbi->fsinfo_sector);		} else {			sbi->free_clusters = CF_LE_L(fsinfo->free_clusters);		}		if (fsinfo_block != 0)			brelse(fsinfo_bh);	} else {		fat32 = 0;		sbi->fat_length = CF_LE_W(b->fat_length);		sbi->root_cluster = 0;		sbi->free_clusters = -1; /* Don't know yet */	}	sbi->dir_per_block = logical_sector_size / 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 =		CF_LE_W(get_unaligned((unsigned short *)&b->dir_entries));	rootdir_sectors = sbi->dir_entries		* sizeof(struct msdos_dir_entry) / logical_sector_size;	sbi->data_start = sbi->dir_start + rootdir_sectors;	total_sectors = CF_LE_W(get_unaligned((unsigned short *)&b->sectors));	if (total_sectors == 0)		total_sectors = CF_LE_L(b->total_sect);	sbi->clusters = (total_sectors - sbi->data_start) / sbi->cluster_size;	error = 0;	if (!error) {		sbi->fat_bits = fat32 ? 32 :			(fat ? fat :			 (sbi->clusters > MSDOS_FAT12 ? 16 : 12));		fat_clusters =			sbi->fat_length * logical_sector_size * 8 / sbi->fat_bits;		error = !sbi->fats || (sbi->dir_entries & (sbi->dir_per_block - 1))			|| sbi->clusters + 2 > fat_clusters + MSDOS_MAX_EXTRA			|| logical_sector_size < 512			|| PAGE_CACHE_SIZE < logical_sector_size			|| !b->secs_track || !b->heads;	}	brelse(bh);	if (error)		goto out_invalid;	sb->s_blocksize = logical_sector_size;	sb->s_blocksize_bits = ffs(logical_sector_size) - 1;	set_blocksize(sb->s_dev, sb->s_blocksize);	sbi->cvf_format = &default_cvf;	if (!strcmp(cvf_format, "none"))		i = -1;	else		i = detect_cvf(sb,cvf_format);	if (i >= 0)		error = cvf_formats[i]->mount_cvf(sb, cvf_options);	if (error || debug) {		/* The MSDOS_CAN_BMAP is obsolete, but left just to remember */		printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"		       "uid=%d,gid=%d,umask=%03o%s]\n",		       sbi->fat_bits,opts.name_check,		       opts.conversion,opts.fs_uid,opts.fs_gid,opts.fs_umask,		       MSDOS_CAN_BMAP(sbi) ? ",bmap" : "");		printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%ld,ds=%ld,de=%d,data=%ld,"		       "se=%u,ts=%u,ls=%d,rc=%ld,fc=%u]\n",		       b->media, sbi->cluster_size, sbi->fats,		       sbi->fat_start, sbi->fat_length, sbi->dir_start,		       sbi->dir_entries, sbi->data_start,		       CF_LE_W(get_unaligned((unsigned short *)&b->sectors)),		       CF_LE_L(b->total_sect), logical_sector_size,		       sbi->root_cluster, sbi->free_clusters);		printk ("hard sector size = %d\n", hard_blksize);	}	if (i < 0)		if (sbi->clusters + 2 > fat_clusters)			sbi->clusters = fat_clusters - 2;	if (error)		goto out_invalid;	sb->s_magic = MSDOS_SUPER_MAGIC;	/* set up enough so that it can read an inode */	init_MUTEX(&sbi->fat_lock);	sbi->prev_free = 0;	cp = opts.codepage ? opts.codepage : 437;	sprintf(buf, "cp%d", cp);	sbi->nls_disk = load_nls(buf);	if (! sbi->nls_disk) {		/* Fail only if explicit charset specified */		if (opts.codepage != 0)			goto out_fail;		sbi->options.codepage = 0; /* already 0?? */		sbi->nls_disk = load_nls_default();	}	sbi->nls_io = NULL;	if (sbi->options.isvfat && !opts.utf8) {		p = opts.iocharset ? opts.iocharset : CONFIG_NLS_DEFAULT;		sbi->nls_io = load_nls(p);		if (! sbi->nls_io)			/* Fail only if explicit charset specified */			if (opts.iocharset)				goto out_unload_nls;	}	if (! sbi->nls_io)		sbi->nls_io = load_nls_default();	root_inode = new_inode(sb);	if (!root_inode)		goto out_unload_nls;	root_inode->i_ino = MSDOS_ROOT_INO;	fat_read_root(root_inode);	insert_inode_hash(root_inode);	sb->s_root = d_alloc_root(root_inode);	if (!sb->s_root)		goto out_no_root;	if(i >= 0) {		sbi->cvf_format = cvf_formats[i];		++cvf_format_use_count[i];	}	return sb;out_no_root:	printk("FAT: get root inode failed\n");	iput(root_inode);	unload_nls(sbi->nls_io);out_unload_nls:	unload_nls(sbi->nls_disk);	goto out_fail;out_invalid:	if (!silent) {		printk("VFS: Can't find a valid FAT filesystem on dev %s.\n",			kdevname(sb->s_dev));	}out_fail:	if (opts.iocharset) {		printk("FAT: freeing iocharset=%s\n", opts.iocharset);		kfree(opts.iocharset);	}	if(sbi->private_data)		kfree(sbi->private_data);	sbi->private_data = NULL; 	return NULL;}int fat_statfs(struct super_block *sb,struct statfs *buf){	int free,nr;       	if (MSDOS_SB(sb)->cvf_format &&	    MSDOS_SB(sb)->cvf_format->cvf_statfs)		return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,						sizeof(struct statfs));	  	lock_fat(sb);	if (MSDOS_SB(sb)->free_clusters != -1)		free = MSDOS_SB(sb)->free_clusters;	else {		free = 0;		for (nr = 2; nr < MSDOS_SB(sb)->clusters+2; nr++)			if (!fat_access(sb,nr,-1)) free++;		MSDOS_SB(sb)->free_clusters = free;	}	unlock_fat(sb);	buf->f_type = sb->s_magic;	buf->f_bsize = 1 << MSDOS_SB(sb)->cluster_bits;	buf->f_blocks = MSDOS_SB(sb)->clusters;	buf->f_bfree = free;	buf->f_bavail = free;	buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;	return 0;}static int is_exec(char *extension){	char *exe_extensions = "EXECOMBAT", *walk;	for (walk = exe_extensions; *walk; walk += 3)		if (!strncmp(extension, walk, 3))			return 1;	return 0;}static int fat_writepage(struct page *page){	return block_write_full_page(page,fat_get_block);}static int fat_readpage(struct file *file, struct page *page){	return block_read_full_page(page,fat_get_block);}static int fat_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){	return cont_prepare_write(page,from,to,fat_get_block,		&MSDOS_I(page->mapping->host)->mmu_private);}static int _fat_bmap(struct address_space *mapping, long block){	return generic_block_bmap(mapping,block,fat_get_block);}static struct address_space_operations fat_aops = {	readpage: fat_readpage,	writepage: fat_writepage,	sync_page: block_sync_page,	prepare_write: fat_prepare_write,	commit_write: generic_commit_write,	bmap: _fat_bmap};/* doesn't deal with root inode */static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de){	struct super_block *sb = inode->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	int nr;	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);	MSDOS_I(inode)->i_location = 0;	MSDOS_I(inode)->i_fat_inode = inode;	inode->i_uid = sbi->options.fs_uid;	inode->i_gid = sbi->options.fs_gid;	inode->i_version = ++event;	inode->i_generation = CURRENT_TIME;		if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {		inode->i_generation &= ~1;		inode->i_mode = MSDOS_MKMODE(de->attr,S_IRWXUGO &		    ~sbi->options.fs_umask) | S_IFDIR;		inode->i_op = sbi->dir_ops;		inode->i_fop = &fat_dir_operations;		MSDOS_I(inode)->i_start = CF_LE_W(de->start);		if (sbi->fat_bits == 32) {			MSDOS_I(inode)->i_start |=				(CF_LE_W(de->starthi) << 16);		}		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;		inode->i_nlink = fat_subdirs(inode);		    /* includes .., compensating for "self" */#ifdef DEBUG		if (!inode->i_nlink) {			printk("directory %d: i_nlink == 0\n",inode->i_ino);			inode->i_nlink = 1;		}#endif		if ((nr = MSDOS_I(inode)->i_start) != 0)			while (nr != -1) {				inode->i_size += 1 << sbi->cluster_bits;				if (!(nr = fat_access(sb, nr, -1))) {					printk("Directory %ld: bad FAT\n",					    inode->i_ino);					break;				}			}		MSDOS_I(inode)->mmu_private = inode->i_size;	} else { /* not a directory */		inode->i_generation |= 1;		inode->i_mode = MSDOS_MKMODE(de->attr,		    ((sbi->options.showexec &&		       !is_exec(de->ext))		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)		    & ~sbi->options.fs_umask) | S_IFREG;		MSDOS_I(inode)->i_start = CF_LE_W(de->start);		if (sbi->fat_bits == 32) {			MSDOS_I(inode)->i_start |=				(CF_LE_W(de->starthi) << 16);		}		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;		inode->i_size = CF_LE_L(de->size);	        inode->i_op = &fat_file_inode_operations;	        inode->i_fop = &fat_file_operations;		inode->i_mapping->a_ops = &fat_aops;		MSDOS_I(inode)->mmu_private = inode->i_size;	}	if(de->attr & ATTR_SYS)		if (sbi->options.sys_immutable)			inode->i_flags |= S_IMMUTABLE;	MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;	/* this is as close to the truth as we can get ... */	inode->i_blksize = 1 << sbi->cluster_bits;	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)			   & ~(inode->i_blksize - 1)) >> 9;	inode->i_mtime = inode->i_atime =		date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));	inode->i_ctime =		MSDOS_SB(sb)->options.isvfat		? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))		: inode->i_mtime;	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;}void fat_write_inode(struct inode *inode, int wait){	struct super_block *sb = inode->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *raw_entry;	unsigned int i_pos;retry:	i_pos = MSDOS_I(inode)->i_location;	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {		return;	}	lock_kernel();	if (!(bh = fat_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {		printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);		fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");		unlock_kernel();		return;	}	spin_lock(&fat_inode_lock);	if (i_pos != MSDOS_I(inode)->i_location) {		spin_unlock(&fat_inode_lock);		fat_brelse(sb, bh);		unlock_kernel();		goto retry;	}	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))	    [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)];	if (S_ISDIR(inode->i_mode)) {		raw_entry->attr = ATTR_DIR;		raw_entry->size = 0;	}	else {		raw_entry->attr = ATTR_NONE;		raw_entry->size = CT_LE_L(inode->i_size);	}	raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |	    MSDOS_I(inode)->i_attrs;	raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);	raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);	fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);	raw_entry->time = CT_LE_W(raw_entry->time);	raw_entry->date = CT_LE_W(raw_entry->date);	if (MSDOS_SB(sb)->options.isvfat) {		fat_date_unix2dos(inode->i_ctime,&raw_entry->ctime,&raw_entry->cdate);		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms;		raw_entry->ctime = CT_LE_W(raw_entry->ctime);		raw_entry->cdate = CT_LE_W(raw_entry->cdate);	}	spin_unlock(&fat_inode_lock);	fat_mark_buffer_dirty(sb, bh);	fat_brelse(sb, bh);	unlock_kernel();}int fat_notify_change(struct dentry * dentry, struct iattr * attr){	struct super_block *sb = dentry->d_sb;	struct inode *inode = dentry->d_inode;	int error;	/* FAT cannot truncate to a longer file */	if (attr->ia_valid & ATTR_SIZE) {		if (attr->ia_size > inode->i_size)			return -EPERM;	}	error = inode_change_ok(inode, attr);	if (error)		return MSDOS_SB(sb)->options.quiet ? 0 : error;	if (((attr->ia_valid & ATTR_UID) && 	     (attr->ia_uid != MSDOS_SB(sb)->options.fs_uid)) ||	    ((attr->ia_valid & ATTR_GID) && 	     (attr->ia_gid != MSDOS_SB(sb)->options.fs_gid)) ||	    ((attr->ia_valid & ATTR_MODE) &&	     (attr->ia_mode & ~MSDOS_VALID_MODE)))		error = -EPERM;	if (error)		return MSDOS_SB(sb)->options.quiet ? 0 : error;	error = inode_setattr(inode, attr);	if (error)		return error;	if (S_ISDIR(inode->i_mode))		inode->i_mode |= S_IXUGO;	inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU	    & ~MSDOS_SB(sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &	    ~MSDOS_SB(sb)->options.fs_umask;	return 0;}MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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