jffs2文件系统——写操作

ramfs系统中write过程浅析中已经大致分析了vfs中写入的过程,jffs2大致跟这个过程差不多,略有差异的是 generic_file_buffered_write函数中的 a_ops->prepare_write和a_ops->commit_writ,这两个函数各文件系统有差异。在jffs2文件系统中如此定义
.readpage =	jffs2_readpage,
.prepare_write =jffs2_prepare_write,
.commit_write =	jffs2_commit_write

jffs2_prepart_write这个函数主要是写入前准备。

commit_write这个函数才是真的数据写入。

static int jffs2_prepare_write (struct file *filp, struct page *pg,
				unsigned start, unsigned end)
{
	struct inode *inode = pg->mapping->host;	//对应的inode
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	//得到这个inode信息
	uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;	//页偏移量,在第几页*4k

	if (pageofs > inode->i_size) {	//超过原来尺寸,有新数据写入
		ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
					  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);	//分配空间,并生成一个jffs2_raw_node_ref

		//下面开始给inode赋值
		……
		ri.data_crc = cpu_to_je32(0);

		fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL);	//写进去了,但是data是NULL的

		if (IS_ERR(fn)) {
			ret = PTR_ERR(fn);
			jffs2_complete_reservation(c);
			up(&f->sem);
			return ret;
		}
		ret = jffs2_add_full_dnode_to_inode(c, f, fn);	//插入一个frag到f中,
		if (f->metadata) {	//将原来数据过期
			jffs2_mark_node_obsolete(c, f->metadata->raw);
			jffs2_free_full_dnode(f->metadata);
			f->metadata = NULL;
		}
		jffs2_complete_reservation(c);
		inode->i_size = pageofs;
	}

}
一般情况下,如果写入的偏移(ofs)超过节点的大小(i_size),这个函数才会起作用,分配新的空间,且写入data为null的节点,生成fn并加到f->fragment的红黑树上。fn上有node的物理地址信息,数据的ofs和size。

static int jffs2_commit_write (struct file *filp, struct page *pg,
			       unsigned start, unsigned end)
{

	ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + aligned_start,
				      (pg->index << PAGE_CACHE_SHIFT) + aligned_start,
				      end - aligned_start, &writtenlen);
	//入口参数:超级块,inode_info,ri,写入数据的位置,偏移,长度,返回值
	//这个偏移很关键,它跟物理地址没关系,就一个page内的偏移
	//将数据mapping(内存)上的数据写入flash

}
其他校验的代码去掉后,剩下本人觉得最重要的代码jffs2_write_inode_range
/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
   we don't have to go digging in struct inode or its equivalent. It should set:
   mode, uid, gid, (starting)isize, atime, ctime, mtime */
int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
			    struct jffs2_raw_inode *ri, unsigned char *buf,
			    uint32_t offset, uint32_t writelen, uint32_t *retlen)
{

	while(writelen) {	//按照长度写完
	retry:
		ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
					&alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
		datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));//存在超出一页的情况
		cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);//跨区

		comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);	//压缩数据
		//写进去的数据是压缩过的

		ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));

		fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
		//入口参数:sb_info,inode_info,ri,data,datalen,mode;返回full_dnode
		//fn->size=dsize
		//fn->raw是节点信息,里面有物理地址信息
		//fn->ofs=ri.offset

		jffs2_free_comprbuf(comprbuf, buf);	//释放压缩后的数据

		ret = jffs2_add_full_dnode_to_inode(c, f, fn);
		if (f->metadata) {//将原来的数据过期掉
			jffs2_mark_node_obsolete(c, f->metadata->raw);
			jffs2_free_full_dnode(f->metadata);
			f->metadata = NULL;
		}
		jffs2_complete_reservation(c);
	}
}

这个函数是将需要写入的数据压缩,后写到通过jffs2_write_dnode将数据写到flash中。并将写入的node信息fn,挂到f->fragment树上





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值