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

📄 wbuf.c

📁 jffs2源代码基于2。6内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Now splitvec points to the start of the bits we have to copy	   into the wbuf */	wbuf_ptr = c->wbuf;	for ( ; splitvec < outvec; splitvec++) {		/* Don't copy the wbuf into itself */		if (outvecs[splitvec].iov_base == c->wbuf)			continue;		memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len);		wbuf_ptr += outvecs[splitvec].iov_len;		donelen += outvecs[splitvec].iov_len;	}	c->wbuf_len = wbuf_ptr - c->wbuf;	/* If there's a remainder in the wbuf and it's a non-GC write,	   remember that the wbuf affects this ino */alldone:	*retlen = donelen;	if (c->wbuf_len && ino)		jffs2_wbuf_dirties_inode(c, ino);	return 0;}/* *	This is the entry for flash write. *	Check, if we work on NAND FLASH, if so build an kvec and write it via vritev*/int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf){	struct kvec vecs[1];	if (jffs2_can_mark_obsolete(c))		return c->mtd->write(c->mtd, ofs, len, retlen, buf);	vecs[0].iov_base = (unsigned char *) buf;	vecs[0].iov_len = len;	return jffs2_flash_writev(c, vecs, 1, ofs, retlen, 0);}/*	Handle readback from writebuffer and ECC failure return*/int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf){	loff_t	orbf = 0, owbf = 0, lwbf = 0;	int	ret;	/* Read flash */	if (!jffs2_can_mark_obsolete(c)) {		ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);		if ( (ret == -EBADMSG) && (*retlen == len) ) {			printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",			       len, ofs);			/* 			 * We have the raw data without ECC correction in the buffer, maybe 			 * we are lucky and all data or parts are correct. We check the node.			 * If data are corrupted node check will sort it out.			 * We keep this block, it will fail on write or erase and the we			 * mark it bad. Or should we do that now? But we should give him a chance.			 * Maybe we had a system crash or power loss before the ecc write or  			 * a erase was completed.			 * So we return success. :)			 */		 	ret = 0;		 }		} else		return c->mtd->read(c->mtd, ofs, len, retlen, buf);	/* if no writebuffer available or write buffer empty, return */	if (!c->wbuf_pagesize || !c->wbuf_len)		return ret;	/* if we read in a different block, return */	if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) 		return ret;		if (ofs >= c->wbuf_ofs) {		owbf = (ofs - c->wbuf_ofs);	/* offset in write buffer */		if (owbf > c->wbuf_len)		/* is read beyond write buffer ? */			return ret;		lwbf = c->wbuf_len - owbf;	/* number of bytes to copy */		if (lwbf > len)				lwbf = len;	} else {			orbf = (c->wbuf_ofs - ofs);	/* offset in read buffer */		if (orbf > len)			/* is write beyond write buffer ? */			return ret;		lwbf = len - orbf; 		/* number of bytes to copy */		if (lwbf > c->wbuf_len)				lwbf = c->wbuf_len;	}		if (lwbf > 0)		memcpy(buf+orbf,c->wbuf+owbf,lwbf);	return ret;}/* *	Check, if the out of band area is empty */int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode){	unsigned char *buf;	int 	ret = 0;	int	i,len,page;	size_t  retlen;	int	oob_size;	/* allocate a buffer for all oob data in this sector */	oob_size = c->mtd->oobsize;	len = 4 * oob_size;	buf = kmalloc(len, GFP_KERNEL);	if (!buf) {		printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");		return -ENOMEM;	}	/* 	 * if mode = 0, we scan for a total empty oob area, else we have	 * to take care of the cleanmarker in the first page of the block	*/	ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);	if (ret) {		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));		goto out;	}		if (retlen < len) {		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read "			  "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset));		ret = -EIO;		goto out;	}		/* Special check for first page */	for(i = 0; i < oob_size ; i++) {		/* Yeah, we know about the cleanmarker. */		if (mode && i >= c->fsdata_pos && 		    i < c->fsdata_pos + c->fsdata_len)			continue;		if (buf[i] != 0xFF) {			D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n",				  buf[page+i], page+i, jeb->offset));			ret = 1; 			goto out;		}	}	/* we know, we are aligned :) */		for (page = oob_size; page < len; page += sizeof(long)) {		unsigned long dat = *(unsigned long *)(&buf[page]);		if(dat != -1) {			ret = 1; 			goto out;		}	}out:	kfree(buf);			return ret;}/**	Scan for a valid cleanmarker and for bad blocks*	For virtual blocks (concatenated physical blocks) check the cleanmarker*	only in the first page of the first physical block, but scan for bad blocks in all*	physical blocks*/int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb){	struct jffs2_unknown_node n;	unsigned char buf[2 * NAND_MAX_OOBSIZE];	unsigned char *p;	int ret, i, cnt, retval = 0;	size_t retlen, offset;	int oob_size;	offset = jeb->offset;	oob_size = c->mtd->oobsize;	/* Loop through the physical blocks */	for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {		/* Check first if the block is bad. */		if (c->mtd->block_isbad (c->mtd, offset)) {			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));			return 2;		}		/*		   *    We read oob data from page 0 and 1 of the block.		   *    page 0 contains cleanmarker and badblock info		   *    page 1 contains failure count of this block		 */		ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);		if (ret) {			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));			return ret;		}		if (retlen < (oob_size << 1)) {			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset));			return -EIO;		}		/* Check cleanmarker only on the first physical block */		if (!cnt) {			n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);			n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);			n.totlen = cpu_to_je32 (8);			p = (unsigned char *) &n;			for (i = 0; i < c->fsdata_len; i++) {				if (buf[c->fsdata_pos + i] != p[i]) {					retval = 1;				}			}			D1(if (retval == 1) {				printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);				printk(KERN_WARNING "OOB at %08x was ", offset);				for (i=0; i < oob_size; i++) {					printk("%02x ", buf[i]);				}				printk("\n");			})		}		offset += c->mtd->erasesize;	}	return retval;}int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb){	struct 	jffs2_unknown_node n;	int 	ret;	size_t 	retlen;	n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);	n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);	n.totlen = cpu_to_je32(8);	ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);		if (ret) {		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));		return ret;	}	if (retlen != c->fsdata_len) {		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));		return ret;	}	return 0;}/*  * On NAND we try to mark this block bad. If the block was erased more * than MAX_ERASE_FAILURES we mark it finaly bad. * Don't care about failures. This block remains on the erase-pending * or badblock list as long as nobody manipulates the flash with * a bootloader or something like that. */int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset){	int 	ret;	/* if the count is < max, we try to write the counter to the 2nd page oob area */	if( ++jeb->bad_count < MAX_ERASE_FAILURES)		return 0;	if (!c->mtd->block_markbad)		return 1; // What else can we do?	D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset));	ret = c->mtd->block_markbad(c->mtd, bad_offset);		if (ret) {		D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret));		return ret;	}	return 1;}#define NAND_JFFS2_OOB16_FSDALEN	8static struct nand_oobinfo jffs2_oobinfo_docecc = {	.useecc = MTD_NANDECC_PLACE,	.eccbytes = 6,	.eccpos = {0,1,2,3,4,5}};int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c){	struct nand_oobinfo *oinfo = &c->mtd->oobinfo;	/* Do this only, if we have an oob buffer */	if (!c->mtd->oobsize)		return 0;		/* Cleanmarker is out-of-band, so inline size zero */	c->cleanmarker_size = 0;	/* Should we use autoplacement ? */	if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {		D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));		/* Get the position of the free bytes */		if (!oinfo->oobfree[0][1]) {			printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");			return -ENOSPC;		}		c->fsdata_pos = oinfo->oobfree[0][0];		c->fsdata_len = oinfo->oobfree[0][1];		if (c->fsdata_len > 8)			c->fsdata_len = 8;	} else {		/* This is just a legacy fallback and should go away soon */		switch(c->mtd->ecctype) {		case MTD_ECC_RS_DiskOnChip:			printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");			c->oobinfo = &jffs2_oobinfo_docecc;			c->fsdata_pos = 6;			c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;			c->badblock_pos = 15;			break;			default:			D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));			return -EINVAL;		}	}	return 0;}int jffs2_nand_flash_setup(struct jffs2_sb_info *c){	int res;	/* Initialise write buffer */	c->wbuf_pagesize = c->mtd->oobblock;	c->wbuf_ofs = 0xFFFFFFFF;		c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);	if (!c->wbuf)		return -ENOMEM;	res = jffs2_nand_set_oobinfo(c);#ifdef BREAKME	if (!brokenbuf)		brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);	if (!brokenbuf) {		kfree(c->wbuf);		return -ENOMEM;	}	memset(brokenbuf, 0xdb, c->wbuf_pagesize);#endif	return res;}void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c){	kfree(c->wbuf);}

⌨️ 快捷键说明

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