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

📄 inode.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    /* Force the superblock to a larger size here. */	    sb->s_blocksize = blksize;	    set_blocksize(sb->s_dev, blksize);	  }	else	  {	    /* The first read is always 1024 bytes */	    sb->s_blocksize = 1024;	    set_blocksize(sb->s_dev, 1024);	  }	bh = bread(sb->s_dev, 0, sb->s_blocksize);	if (bh == NULL || !buffer_uptodate(bh)) {		brelse (bh);		goto out_no_bread;	}/* * 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) */#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)    /* don't divide by zero */	b = (struct fat_boot_sector *) bh->b_data;	logical_sector_size =		CF_LE_W(get_unaligned((unsigned short *) &b->sector_size));	sector_mult = logical_sector_size >> SECTOR_BITS;	sbi->cluster_size = b->cluster_size*sector_mult;	if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size-1))) {		printk("fatfs: bogus cluster size\n");		brelse(bh);		goto out_invalid;	}	for (sbi->cluster_bits=0;	     1<<sbi->cluster_bits<sbi->cluster_size;	     sbi->cluster_bits++)		;	sbi->cluster_bits += SECTOR_BITS;	sbi->fats = b->fats;	sbi->fat_start = CF_LE_W(b->reserved)*sector_mult;	if (!b->fat_length && b->fat32_length) {		struct fat_boot_fsinfo *fsinfo;		/* Must be FAT32 */		fat32 = 1;		sbi->fat_length= CF_LE_L(b->fat32_length)*sector_mult;		sbi->root_cluster = CF_LE_L(b->root_cluster);		/* MC - if info_sector is 0, don't multiply by 0 */		if(CF_LE_W(b->info_sector) == 0) {			sbi->fsinfo_offset =	 			logical_sector_size + 0x1e0;		} else {			sbi->fsinfo_offset =				(CF_LE_W(b->info_sector) * logical_sector_size)				+ 0x1e0;		}		if (sbi->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) {			printk("fat_read_super: Bad fsinfo_offset\n");			brelse(bh);			goto out_invalid;		}		fsinfo = (struct fat_boot_fsinfo *)			&bh->b_data[sbi->fsinfo_offset];		if (CF_LE_L(fsinfo->signature) != 0x61417272) {			printk("fat_read_super: Did not find valid FSINFO "				"signature. Found 0x%x\n",				CF_LE_L(fsinfo->signature));		} else {			sbi->free_clusters = CF_LE_L(fsinfo->free_clusters);		}	} else {		fat32 = 0;		sbi->fat_length = CF_LE_W(b->fat_length)*sector_mult;		sbi->root_cluster = 0;		sbi->free_clusters = -1; /* Don't know yet */	}	sbi->dir_start= CF_LE_W(b->reserved)*sector_mult+	    b->fats*sbi->fat_length;	sbi->dir_entries =		CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries));	sbi->data_start = sbi->dir_start+ROUND_TO_MULTIPLE((	    sbi->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,	    sector_mult);	data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors));	if (!data_sectors) {		data_sectors = CF_LE_L(b->total_sect);	}	data_sectors = data_sectors * sector_mult - sbi->data_start;	error = !b->cluster_size || !sector_mult;	if (!error) {		sbi->clusters = b->cluster_size ? data_sectors/		    b->cluster_size/sector_mult : 0;		sbi->fat_bits = fat32 ? 32 :			(fat ? fat :			 (sbi->clusters > MSDOS_FAT12 ? 16 : 12));		fat_clusters = sbi->fat_length*SECTOR_SIZE*8/		    sbi->fat_bits;		error = !sbi->fats || (sbi->dir_entries &		    (MSDOS_DPS-1)) || sbi->clusters+2 > fat_clusters+		    MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))		    || !b->secs_track || !b->heads;	}	brelse(bh);	set_blocksize(sb->s_dev, blksize);	/*		This must be done after the brelse because the bh is a dummy		allocated by fat_bread (see buffer.c)	*/	sb->s_blocksize = blksize;    /* Using this small block size solves */				/* the misfit with buffer cache and cluster */				/* because clusters (DOS) are often aligned */				/* on odd sectors. */	sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);	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);	else if (sb->s_blocksize == 512)		sbi->cvf_format = &default_cvf;	else		sbi->cvf_format = &bigblock_cvf;	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=%d,ts=%ld,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(*(unsigned short *) &b->sectors),		       (unsigned long)b->total_sect,logical_sector_size,		       sbi->root_cluster,sbi->free_clusters);		printk ("Transaction block size = %d\n",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_waitqueue_head(&sbi->fat_wait);	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("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 MSDOS filesystem on dev %s.\n",			kdevname(sb->s_dev));	goto out_fail;out_no_bread:	printk("FAT bread failed\n");out_fail:	if (opts.iocharset) {		printk("VFS: 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 = MSDOS_SB(sb)->cluster_size*SECTOR_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(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;	if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {		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 += SECTOR_SIZE*sbi->cluster_size;				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_mode = MSDOS_MKMODE(de->attr,		    ((IS_NOEXEC(inode) || 		      (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 = sbi->cluster_size*SECTOR_SIZE;	inode->i_blocks =		((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *		sbi->cluster_size;	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;	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_DPB_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_DPB-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;	inode_setattr(inode, attr);	if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))		inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;	else		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;}

⌨️ 快捷键说明

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