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

📄 file.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (bh) {			bh->b_state |= tmp_bh.b_state;			return bh;		}		err = -EIO;	}	return ERR_PTR(err);}static inline struct buffer_head *affs_getemptyblk_ino(struct inode *inode, int block){	struct buffer_head *bh, tmp_bh;	int err;	tmp_bh.b_state = 0;	err = affs_get_block(inode, block, &tmp_bh, 1);	if (!err) {		bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);		if (bh) {			bh->b_state |= tmp_bh.b_state;			return bh;		}		err = -EIO;	}	return ERR_PTR(err);}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 intaffs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to){	struct inode *inode = page->mapping->host;	struct super_block *sb = inode->i_sb;	struct buffer_head *bh;	char *data;	u32 bidx, boff, bsize;	u32 tmp;	pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);	if (from > to || to > PAGE_CACHE_SIZE)		BUG();	data = page_address(page);	bsize = AFFS_SB->s_data_blksize;	tmp = (page->index << PAGE_CACHE_SHIFT) + from;	bidx = tmp / bsize;	boff = tmp % bsize;	while (from < to) {		bh = affs_bread_ino(inode, bidx, 0);		if (IS_ERR(bh))			return PTR_ERR(bh);		tmp = min(bsize - boff, to - from);		if (from + tmp > to || tmp > bsize)			BUG();		memcpy(data + from, AFFS_DATA(bh) + boff, tmp);		affs_brelse(bh);		bidx++;		from += tmp;		boff = 0;	}	return 0;}static intaffs_extent_file_ofs(struct inode *inode, u32 newsize){	struct super_block *sb = inode->i_sb;	struct buffer_head *bh, *prev_bh;	u32 bidx, boff;	u32 size, bsize;	u32 tmp;	pr_debug("AFFS: extent_file(%u, %d)\n", (u32)inode->i_ino, newsize);	bsize = AFFS_SB->s_data_blksize;	bh = NULL;	size = AFFS_INODE->mmu_private;	bidx = size / bsize;	boff = size % bsize;	if (boff) {		bh = affs_bread_ino(inode, bidx, 0);		if (IS_ERR(bh))			return PTR_ERR(bh);		tmp = min(bsize - boff, newsize - size);		if (boff + tmp > bsize || tmp > bsize)			BUG();		memset(AFFS_DATA(bh) + boff, 0, tmp);		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);		affs_fix_checksum(sb, bh);		mark_buffer_dirty_inode(bh, inode);		size += tmp;		bidx++;	} else if (bidx) {		bh = affs_bread_ino(inode, bidx - 1, 0);		if (IS_ERR(bh))			return PTR_ERR(bh);	}	while (size < newsize) {		prev_bh = bh;		bh = affs_getzeroblk_ino(inode, bidx);		if (IS_ERR(bh))			goto out;		tmp = min(bsize, newsize - size);		if (tmp > bsize)			BUG();		AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);		AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);		AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);		affs_fix_checksum(sb, bh);		bh->b_state &= ~(1UL << BH_New);		mark_buffer_dirty_inode(bh, inode);		if (prev_bh) {			u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);			if (tmp)				affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);			AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);			affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);			mark_buffer_dirty_inode(prev_bh, inode);			affs_brelse(prev_bh);		}		size += bsize;		bidx++;	}	affs_brelse(bh);	inode->i_size = AFFS_INODE->mmu_private = newsize;	return 0;out:	inode->i_size = AFFS_INODE->mmu_private = size;	return PTR_ERR(bh);}static intaffs_readpage_ofs(struct file *file, struct page *page){	struct inode *inode = page->mapping->host;	u32 to;	int err;	pr_debug("AFFS: read_page(%u, %ld)\n", (u32)inode->i_ino, page->index);	to = PAGE_CACHE_SIZE;	if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {		to = inode->i_size & ~PAGE_CACHE_MASK;		memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);	}	err = affs_do_readpage_ofs(file, page, 0, to);	if (!err)		SetPageUptodate(page);	UnlockPage(page);	return err;}static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to){	struct inode *inode = page->mapping->host;	u32 size, offset;	u32 tmp;	int err = 0;	pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);	offset = page->index << PAGE_CACHE_SHIFT;	if (offset + from > AFFS_INODE->mmu_private) {		err = affs_extent_file_ofs(inode, offset + from);		if (err)			return err;	}	size = inode->i_size;	if (Page_Uptodate(page))		return 0;	if (from) {		err = affs_do_readpage_ofs(file, page, 0, from);		if (err)			return err;	}	if (to < PAGE_CACHE_SIZE) {		memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);		if (size > offset + to) {			if (size < offset + PAGE_CACHE_SIZE)				tmp = size & ~PAGE_CACHE_MASK;			else				tmp = PAGE_CACHE_SIZE;			err = affs_do_readpage_ofs(file, page, to, tmp);		}	}	return err;}static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to){	struct inode *inode = page->mapping->host;	struct super_block *sb = inode->i_sb;	struct buffer_head *bh, *prev_bh;	char *data;	u32 bidx, boff, bsize;	u32 tmp;	int written;	pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);	bsize = AFFS_SB->s_data_blksize;	data = page_address(page);	bh = NULL;	written = 0;	tmp = (page->index << PAGE_CACHE_SHIFT) + from;	bidx = tmp / bsize;	boff = tmp % bsize;	if (boff) {		bh = affs_bread_ino(inode, bidx, 0);		if (IS_ERR(bh))			return PTR_ERR(bh);		tmp = min(bsize - boff, to - from);		if (boff + tmp > bsize || tmp > bsize)			BUG();		memcpy(AFFS_DATA(bh) + boff, data + from, tmp);		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);		affs_fix_checksum(sb, bh);		mark_buffer_dirty_inode(bh, inode);		written += tmp;		from += tmp;		bidx++;	} else if (bidx) {		bh = affs_bread_ino(inode, bidx - 1, 0);		if (IS_ERR(bh))			return PTR_ERR(bh);	}	while (from + bsize <= to) {		prev_bh = bh;		bh = affs_getemptyblk_ino(inode, bidx);		if (IS_ERR(bh))			goto out;		memcpy(AFFS_DATA(bh), data + from, bsize);		if (bh->b_state & (1UL << BH_New)) {			AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);			AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);			AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);			AFFS_DATA_HEAD(bh)->next = 0;			bh->b_state &= ~(1UL << BH_New);			if (prev_bh) {				u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);				if (tmp)					affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);				affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);				mark_buffer_dirty_inode(prev_bh, inode);			}		}		affs_brelse(prev_bh);		affs_fix_checksum(sb, bh);		mark_buffer_dirty_inode(bh, inode);		written += bsize;		from += bsize;		bidx++;	}	if (from < to) {		prev_bh = bh;		bh = affs_bread_ino(inode, bidx, 1);		if (IS_ERR(bh))			goto out;		tmp = min(bsize, to - from);		if (tmp > bsize)			BUG();		memcpy(AFFS_DATA(bh), data + from, tmp);		if (bh->b_state & (1UL << BH_New)) {			AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);			AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);			AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);			AFFS_DATA_HEAD(bh)->next = 0;			bh->b_state &= ~(1UL << BH_New);			if (prev_bh) {				u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);				if (tmp)					affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);				affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);				mark_buffer_dirty_inode(prev_bh, inode);			}		} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);		affs_brelse(prev_bh);		affs_fix_checksum(sb, bh);		mark_buffer_dirty_inode(bh, inode);		written += tmp;		from += tmp;		bidx++;	}	SetPageUptodate(page);done:	affs_brelse(bh);	tmp = (page->index << PAGE_CACHE_SHIFT) + from;	if (tmp > inode->i_size)		inode->i_size = AFFS_INODE->mmu_private = tmp;	return written;out:	bh = prev_bh;	if (!written)		written = PTR_ERR(bh);	goto done;}struct address_space_operations affs_aops_ofs = {	readpage: affs_readpage_ofs,	//writepage: affs_writepage_ofs,	//sync_page: affs_sync_page_ofs,	prepare_write: affs_prepare_write_ofs,	commit_write: affs_commit_write_ofs};/* Free any preallocated blocks. */voidaffs_free_prealloc(struct inode *inode){	struct super_block *sb = inode->i_sb;	pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);	while (inode->u.affs_i.i_pa_cnt) {		inode->u.affs_i.i_pa_cnt--;		affs_free_block(sb, ++inode->u.affs_i.i_lastalloc);	}}/* Truncate (or enlarge) a file to the requested size. */voidaffs_truncate(struct inode *inode){	struct super_block *sb = inode->i_sb;	u32 ext, ext_key;	u32 last_blk, blkcnt, blk;	u32 size;	struct buffer_head *ext_bh;	int i;	pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",		 (u32)inode->i_ino, (u32)AFFS_INODE->mmu_private, (u32)inode->i_size);	last_blk = 0;	ext = 0;	if (inode->i_size) {		last_blk = ((u32)inode->i_size - 1) / AFFS_SB->s_data_blksize;		ext = last_blk / AFFS_SB->s_hashsize;	}	if (inode->i_size > AFFS_INODE->mmu_private) {		struct address_space *mapping = inode->i_mapping;		struct page *page;		u32 size = inode->i_size - 1;		int res;		page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);		if (!page)			return;		size = (size & (PAGE_CACHE_SIZE - 1)) + 1;		res = mapping->a_ops->prepare_write(NULL, page, size, size);		if (!res)			res = mapping->a_ops->commit_write(NULL, page, size, size);		UnlockPage(page);		page_cache_release(page);		mark_inode_dirty(inode);		return;	} else if (inode->i_size == AFFS_INODE->mmu_private)		return;	// lock cache	ext_bh = affs_get_extblock(inode, ext);	if (IS_ERR(ext_bh)) {		affs_warning(sb, "truncate", "unexpected read error for ext block %u (%d)",			     ext, PTR_ERR(ext_bh));		return;	}	if (AFFS_INODE->i_lc) {		/* clear linear cache */		i = (ext + 1) >> AFFS_INODE->i_lc_shift;		if (AFFS_INODE->i_lc_size > i) {			AFFS_INODE->i_lc_size = i;			for (; i < AFFS_LC_SIZE; i++)				AFFS_INODE->i_lc[i] = 0;		}		/* clear associative cache */		for (i = 0; i < AFFS_AC_SIZE; i++)			if (AFFS_INODE->i_ac[i].ext >= ext)				AFFS_INODE->i_ac[i].ext = 0;	}	ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);	blkcnt = AFFS_INODE->i_blkcnt;	i = 0;	blk = last_blk;	if (inode->i_size) {		i = last_blk % AFFS_SB->s_hashsize + 1;		blk++;	} else		AFFS_HEAD(ext_bh)->first_data = 0;	size = AFFS_SB->s_hashsize;	if (size > blkcnt - blk + i)		size = blkcnt - blk + i;	for (; i < size; i++, blk++) {		affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));		AFFS_BLOCK(sb, ext_bh, i) = 0;	}	AFFS_TAIL(sb, ext_bh)->extension = 0;	affs_fix_checksum(sb, ext_bh);	mark_buffer_dirty_inode(ext_bh, inode);	affs_brelse(ext_bh);	if (inode->i_size) {		AFFS_INODE->i_blkcnt = last_blk + 1;		AFFS_INODE->i_extcnt = ext + 1;		if (AFFS_SB->s_flags & SF_OFS) {			struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);			u32 tmp;			if (IS_ERR(bh)) {				affs_warning(sb, "truncate", "unexpected read error for last block %u (%d)",					     last_blk, PTR_ERR(bh));				return;			}			tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);			AFFS_DATA_HEAD(bh)->next = 0;			affs_adjust_checksum(bh, -tmp);			affs_brelse(bh);		}	} else {		AFFS_INODE->i_blkcnt = 0;		AFFS_INODE->i_extcnt = 1;	}	AFFS_INODE->mmu_private = inode->i_size;	// unlock cache	while (ext_key) {		ext_bh = affs_bread(sb, ext_key);		size = AFFS_SB->s_hashsize;		if (size > blkcnt - blk)			size = blkcnt - blk;		for (i = 0; i < size; i++, blk++)			affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));		affs_free_block(sb, ext_key);		ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);		affs_brelse(ext_bh);	}	affs_free_prealloc(inode);}

⌨️ 快捷键说明

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