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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 = CF_LE_W(b->reserved);	sbi->fat_length = CF_LE_W(b->fat_length);	sbi->root_cluster = 0;	sbi->free_clusters = -1;	/* Don't know yet */	sbi->prev_free = -1;	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 = CF_LE_L(b->fat32_length);		sbi->root_cluster = CF_LE_L(b->root_cluster);		sb->s_maxbytes = 0xffffffff;				/* MC - if info_sector is 0, don't multiply by 0 */		sbi->fsinfo_sector = CF_LE_W(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: Did not find valid FSINFO signature.\n"			       "     Found signature1 0x%08x signature2 0x%08x"			       " (sector = %lu)\n",			       CF_LE_L(fsinfo->signature1),			       CF_LE_L(fsinfo->signature2),			       sbi->fsinfo_sector);		} else {			sbi->free_clusters = CF_LE_L(fsinfo->free_clusters);			sbi->prev_free = CF_LE_L(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 = CF_LE_W(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 = CF_LE_W(get_unaligned((__le16 *)&b->sectors));	if (total_sectors == 0)		total_sectors = CF_LE_L(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 - 2);	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->clusters = total_clusters;	brelse(bh);	/* validity check of FAT */	first = __fat_access(sb, 0, -1);	if (first < 0) {		error = first;		goto out_fail;	}	if (FAT_FIRST_ENT(sb, media) == first) {		/* all is as it should be */	} else if (media == 0xf8 && FAT_FIRST_ENT(sb, 0xfe) == first) {		/* bad, reported on pc9800 */	} else if (media == 0xf0 && FAT_FIRST_ENT(sb, 0xf8) == first) {		/* bad, reported with a MO disk on win95/me */	} else if (first == 0) {		/* bad, reported with a SmartMedia card */	} else {		if (!silent)			printk(KERN_ERR "FAT: invalid first entry of FAT "			       "(0x%x != 0x%x)\n",			       FAT_FIRST_ENT(sb, media), first);		goto out_invalid;	}	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;}int fat_statfs(struct super_block *sb, struct kstatfs *buf){	int free, nr, ret;       	if (MSDOS_SB(sb)->free_clusters != -1)		free = MSDOS_SB(sb)->free_clusters;	else {		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++) {				ret = fat_access(sb, nr, -1);				if (ret < 0) {					unlock_fat(sb);					return ret;				} else if (ret == FAT_ENT_FREE)					free++;			}			MSDOS_SB(sb)->free_clusters = free;		}		unlock_fat(sb);	}	buf->f_type = sb->s_magic;	buf->f_bsize = MSDOS_SB(sb)->cluster_size;	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(unsigned char *extension){	unsigned 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, struct writeback_control *wbc){	return block_write_full_page(page,fat_get_block, wbc);}static int fat_readpage(struct file *file, struct page *page){	return block_read_full_page(page,fat_get_block);}static intfat_prepare_write(struct file *file, struct page *page,			unsigned from, unsigned to){	kmap(page);	return cont_prepare_write(page,from,to,fat_get_block,		&MSDOS_I(page->mapping->host)->mmu_private);}static intfat_commit_write(struct file *file, struct page *page,			unsigned from, unsigned to){	kunmap(page);	return generic_commit_write(file, page, from, to);}static sector_t _fat_bmap(struct address_space *mapping, sector_t 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 = fat_commit_write,	.bmap = _fat_bmap};/* doesn't deal with root inode */static int 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 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 = get_seconds();		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_dmask) | 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;		error = fat_calc_dir_size(inode);		if (error < 0)			return error;		MSDOS_I(inode)->mmu_private = inode->i_size;		inode->i_nlink = fat_subdirs(inode);	} 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_fmask) | 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 = sbi->cluster_size;	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;	inode->i_mtime.tv_sec = inode->i_atime.tv_sec =		date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;	inode->i_ctime.tv_sec =		MSDOS_SB(sb)->options.isvfat		? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))		: inode->i_mtime.tv_sec;	inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;	return 0;}int 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;	loff_t i_pos;retry:	i_pos = MSDOS_I(inode)->i_pos;	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {		return 0;	}	lock_kernel();	if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {		printk(KERN_ERR "FAT: unable to read inode block "		       "for updating (i_pos %lld)\n", i_pos);		unlock_kernel();		return -EIO;	}	spin_lock(&fat_inode_lock);	if (i_pos != MSDOS_I(inode)->i_pos) {		spin_unlock(&fat_inode_lock);		brelse(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.tv_sec, &raw_entry->time, &raw_entry->date);	if (MSDOS_SB(sb)->options.isvfat) {		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */	}	spin_unlock(&fat_inode_lock);	mark_buffer_dirty(bh);	brelse(bh);	unlock_kernel();	return 0;}int fat_notify_change(struct dentry * dentry, struct iattr * attr){	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);	struct inode *inode = dentry->d_inode;	int mask, error = 0;	lock_kernel();	/* FAT cannot truncate to a longer file */	if (attr->ia_valid & ATTR_SIZE) {		if (attr->ia_size > inode->i_size) {			error = -EPERM;			goto out;		}	}	error = inode_change_ok(inode, attr);	if (error) {		if (sbi->options.quiet)			error = 0; 		goto out;	}	if (((attr->ia_valid & ATTR_UID) && 	     (attr->ia_uid != sbi->options.fs_uid)) ||	    ((attr->ia_valid & ATTR_GID) && 	     (attr->ia_gid != sbi->options.fs_gid)) ||	    ((attr->ia_valid & ATTR_MODE) &&	     (attr->ia_mode & ~MSDOS_VALID_MODE)))		error = -EPERM;	if (error) {		if (sbi->options.quiet)  			error = 0;		goto out;	}	error = inode_setattr(inode, attr);	if (error)		goto out;	if (S_ISDIR(inode->i_mode))		mask = sbi->options.fs_dmask;	else		mask = sbi->options.fs_fmask;	inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);out:	unlock_kernel();	return error;}MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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