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

📄 file.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
					pbh = affs_bread(inode->i_dev,							be32_to_cpu(k),							AFFS_I2BSIZE(inode));				} else					pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock);				if (!pbh) {					affs_error(sb,"getblock", "Cannot get last block in file");					break;				}			}			nkey = affs_new_data(inode);			if (!nkey)				break;			inode->u.affs_i.i_lastblock++;			if (AFFS_BLOCK(bh->b_data,inode,j)) {				affs_warning(sb,"getblock","Block already allocated");				affs_free_block(sb,nkey);				continue;			}			AFFS_BLOCK(bh->b_data,inode,j) = cpu_to_be32(nkey);			if (ofs) {				ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode));				if (!ebh) {					affs_error(sb,"getblock", "Cannot get block %d",nkey);					affs_free_block(sb,nkey);					AFFS_BLOCK(bh->b_data,inode,j) = 0;					break;				}				DATA_FRONT(ebh)->primary_type    = cpu_to_be32(T_DATA);				DATA_FRONT(ebh)->header_key      = cpu_to_be32(inode->i_ino);				DATA_FRONT(ebh)->sequence_number = cpu_to_be32(inode->u.affs_i.i_lastblock + 1);				affs_fix_checksum(AFFS_I2BSIZE(inode), ebh->b_data, 5);				mark_buffer_dirty(ebh);				if (pbh) {					DATA_FRONT(pbh)->data_size = cpu_to_be32(AFFS_I2BSIZE(inode) - 24);					DATA_FRONT(pbh)->next_data = cpu_to_be32(nkey);					affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5);					mark_buffer_dirty(pbh);					affs_brelse(pbh);				}				pbh = ebh;			}			cf = 1;		}		/* N.B. May need to release pbh after here */		if (cf) {			if (pt == T_SHORT)				fdp->first_data = AFFS_BLOCK(bh->b_data,inode,0);			fdp->block_count = cpu_to_be32(j);			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);			mark_buffer_dirty(bh);		}		if (block < j) {			if (pbh)				affs_brelse(pbh);			break;		}		if (j < AFFS_I2HSIZE(inode)) {			/* N.B. What about pbh here? */			goto out_free_bh;		}		block -= AFFS_I2HSIZE(inode);		key    = be32_to_cpu(FILE_END(bh->b_data,inode)->extension);		if (!key) {			key = affs_new_header(inode);			if (!key)				goto out_free_bh;			ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));			if (!ebh) {				/* N.B. must free bh here */				goto out_free_block;			}			((struct file_front *)ebh->b_data)->primary_type = cpu_to_be32(T_LIST);			((struct file_front *)ebh->b_data)->own_key      = cpu_to_be32(key);			FILE_END(ebh->b_data,inode)->secondary_type      = cpu_to_be32(ST_FILE);			FILE_END(ebh->b_data,inode)->parent              = cpu_to_be32(inode->i_ino);			affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);			mark_buffer_dirty(ebh);			FILE_END(bh->b_data,inode)->extension = cpu_to_be32(key);			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);			mark_buffer_dirty(bh);			affs_brelse(bh);			bh = ebh;		}		pt = T_LIST;		ext++;		index = seqnum_to_index(ext);		if (index > inode->u.affs_i.i_ec->max_ext &&		    AFFS_ISINDEX(ext)) {			inode->u.affs_i.i_ec->ec[index] = key;			inode->u.affs_i.i_ec->max_ext   = index;		}		affs_brelse(bh);	}	/* Invalidate key cache */	for (j = 0; j < 4; j++) {		kc = &inode->u.affs_i.i_ec->kc[j];		kc->kc_last = -1;	}	key = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,block));	affs_brelse(bh);	if (!key)		goto out_fail;	bh = affs_bread(inode->i_dev, key, AFFS_I2BSIZE(inode));	return bh;out_free_block:	affs_free_block(sb, key);out_free_bh:	affs_brelse(bh);out_fail:	return NULL;}static ssize_taffs_file_read_ofs(struct file *filp, char *buf, size_t count, loff_t *ppos){	struct inode		*inode = filp->f_dentry->d_inode;	char			*start;	ssize_t			 left, offset, size, sector;	ssize_t			 blocksize;	struct buffer_head	*bh;	void			*data;	loff_t		tmp;	pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,		 (unsigned long)*ppos,count);	if (!inode) {		affs_error(inode->i_sb,"file_read_ofs","Inode = NULL");		return -EINVAL;	}	blocksize = AFFS_I2BSIZE(inode) - 24;	if (!(S_ISREG(inode->i_mode))) {		pr_debug("AFFS: file_read: mode = %07o",inode->i_mode);		return -EINVAL;	}	if (*ppos >= inode->i_size || count <= 0)		return 0;	start = buf;	for (;;) {		left = MIN (inode->i_size - *ppos,count - (buf - start));		if (!left)			break;		tmp = *ppos;		do_div(tmp, blocksize);		sector = affs_bmap(inode, tmp);		if (!sector)			break;		tmp = *ppos;		offset = do_div(tmp, blocksize);		bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode));		if (!bh)			break;		data = bh->b_data + 24;		size = MIN(blocksize - offset,left);		*ppos += size;		copy_to_user(buf,data + offset,size);		buf += size;		affs_brelse(bh);	}	if (start == buf)		return -EIO;	return buf - start;}static ssize_taffs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos){	ssize_t retval;	retval = generic_file_write (file, buf, count, ppos);	if (retval >0) {		struct inode *inode = file->f_dentry->d_inode;		inode->i_ctime = inode->i_mtime = CURRENT_TIME;		mark_inode_dirty(inode);	}	return retval;}static ssize_taffs_file_write_ofs(struct file *file, const char *buf, size_t count, loff_t *ppos){	ssize_t retval;	retval = generic_file_write (file, buf, count, ppos);	if (retval >0) {		struct inode *inode = file->f_dentry->d_inode;		inode->i_ctime = inode->i_mtime = CURRENT_TIME;		mark_inode_dirty(inode);	}	return retval;}/* Free any preallocated blocks. */voidaffs_free_prealloc(struct inode *inode){	struct super_block	*sb = inode->i_sb;	struct affs_zone	*zone;	int block;	pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);	while (inode->u.affs_i.i_pa_cnt) {			block = inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++];		inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1;		inode->u.affs_i.i_pa_cnt--;		affs_free_block(sb, block);	}	if (inode->u.affs_i.i_zone) {		zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];		if (zone->z_ino == inode->i_ino)			zone->z_ino = 0;	}}/* Truncate (or enlarge) a file to the requested size. */voidaffs_truncate(struct inode *inode){	struct buffer_head	*bh = NULL;	int	 first;			/* First block to be thrown away	*/	int	 block;	s32	 key;	s32	*keyp;	s32	 ekey;	s32	 ptype, stype;	int	 freethis;	int	 net_blocksize;	int	 blocksize = AFFS_I2BSIZE(inode);	int	 rem;	int	 ext;	loff_t tmp;	pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);	net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);	first = inode->i_size + net_blocksize -1;	do_div (first, net_blocksize);	if (inode->u.affs_i.i_lastblock < first - 1) {		/* There has to be at least one new block to be allocated */		if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) {			/* XXX Fine! No way to indicate an error. */			return /* -ENOSPC */;		}		bh = affs_getblock(inode,first - 1);		if (!bh) {			affs_warning(inode->i_sb,"truncate","Cannot extend file");			inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1);		} else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {			tmp = inode->i_size;			rem = do_div(tmp, net_blocksize);			DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize);			affs_fix_checksum(blocksize,bh->b_data,5);			mark_buffer_dirty(bh);		}		goto out_truncate;	}	ekey = inode->i_ino;	ext  = 0;	/* Free all blocks starting at 'first' and all then-empty	 * extension blocks. Do not free the header block, though.	 */	while (ekey) {		if (!(bh = affs_bread(inode->i_dev,ekey,blocksize))) {			affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey);			goto out_truncate;		}		if (affs_checksum_block(blocksize,bh->b_data,&ptype,&stype)) {			affs_error(inode->i_sb,"truncate","Checksum error in header/ext block %d",				   ekey);			goto out_truncate;		}		if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {			affs_error(inode->i_sb,"truncate",				   "Bad block (key=%d, ptype=%d, stype=%d)",ekey,ptype,stype);			goto out_truncate;		}		/* Do we have to free this extension block after		 * freeing the data blocks pointed to?		 */		freethis = first == 0 && ekey != inode->i_ino;		/* Free the data blocks. 'first' is relative to this		 * extension block and may well lie behind this block.		 */		for (block = first; block < AFFS_I2HSIZE(inode); block++) {			keyp = &AFFS_BLOCK(bh->b_data,inode,block);			key  = be32_to_cpu(*keyp);			if (key) {				*keyp = 0;				affs_free_block(inode->i_sb,key);			} else				break;		}		keyp = &GET_END_PTR(struct file_end,bh->b_data,blocksize)->extension;		key  = be32_to_cpu(*keyp);		/* If 'first' is in this block or is the first		 * in the next one, this will be the last in		 * the list, thus we have to adjust the count		 * and zero the pointer to the next ext block.		 */		if (first <= AFFS_I2HSIZE(inode)) {			((struct file_front *)bh->b_data)->block_count = cpu_to_be32(first);			first = 0;			*keyp = 0;			affs_fix_checksum(blocksize,bh->b_data,5);			mark_buffer_dirty(bh);		} else			first -= AFFS_I2HSIZE(inode);		affs_brelse(bh);		bh = NULL;		if (freethis)			/* Don't bother fixing checksum */			affs_free_block(inode->i_sb,ekey);		ekey = key;	}	block = inode->i_size + net_blocksize - 1;	do_div (block, net_blocksize);	block--;	inode->u.affs_i.i_lastblock = block;	/* If the file is not truncated to a block boundary,	 * the partial block after the EOF must be zeroed	 * so it cannot become accessible again.	 */	tmp = inode->i_size;	rem = do_div(tmp, net_blocksize);	if (rem) {		if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) 			rem += 24;		pr_debug("AFFS: Zeroing from offset %d in block %d\n",rem,block);		bh = affs_getblock(inode,block);		if (bh) {			memset(bh->b_data + rem,0,blocksize - rem);			if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) {				((struct data_front *)bh->b_data)->data_size = cpu_to_be32(rem);				((struct data_front *)bh->b_data)->next_data = 0;				affs_fix_checksum(blocksize,bh->b_data,5);			}			mark_buffer_dirty(bh);		} else 			affs_error(inode->i_sb,"truncate","Cannot read block %d",block);	}out_truncate:	affs_brelse(bh);	/* Invalidate cache */	if (inode->u.affs_i.i_ec) {		inode->u.affs_i.i_ec->max_ext = 0;		for (key = 0; key < 4; key++) {			inode->u.affs_i.i_ec->kc[key].kc_next_key = 0;			inode->u.affs_i.i_ec->kc[key].kc_last     = -1;		}	}	mark_inode_dirty(inode);}/* * Called only when we need to allocate the extension cache. */static intalloc_ext_cache(struct inode *inode){	s32	 key;	int	 i;	unsigned long cache_page;	int      error = 0;	pr_debug("AFFS: alloc_ext_cache(ino=%lu)\n",inode->i_ino);	cache_page = get_free_page(GFP_KERNEL);	/*	 * Check whether somebody else allocated it for us ...	 */	if (inode->u.affs_i.i_ec)		goto out_free;	if (!cache_page)		goto out_error;	inode->u.affs_i.i_ec = (struct ext_cache *) cache_page;	/* We only have to initialize non-zero values.	 * get_free_page() zeroed the page already.	 */	key = inode->i_ino;	inode->u.affs_i.i_ec->ec[0] = key;	for (i = 0; i < 4; i++) {		inode->u.affs_i.i_ec->kc[i].kc_this_key = key;		inode->u.affs_i.i_ec->kc[i].kc_last     = -1;	}out:	return error;out_free:	if (cache_page)		free_page(cache_page);	goto out;out_error:	affs_error(inode->i_sb,"alloc_ext_cache","Cache allocation failed");	error = -ENOMEM;	goto out;}

⌨️ 快捷键说明

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