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

📄 eba.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);		if (err && err != UBI_IO_BITFLIPS) {			if (err > 0) {				/*				 * The header is either absent or corrupted.				 * The former case means there is a bug -				 * switch to read-only mode just in case.				 * The latter case means a real corruption - we				 * may try to recover data. FIXME: but this is				 * not implemented.				 */				if (err == UBI_IO_BAD_VID_HDR) {					ubi_warn("bad VID header at PEB %d, LEB"						 "%d:%d", pnum, vol_id, lnum);					err = -EBADMSG;				} else					ubi_ro_mode(ubi);			}			goto out_free;		} else if (err == UBI_IO_BITFLIPS)			scrub = 1;		ubi_assert(lnum < be32_to_cpu(vid_hdr->used_ebs));		ubi_assert(len == be32_to_cpu(vid_hdr->data_size));		crc = be32_to_cpu(vid_hdr->data_crc);		ubi_free_vid_hdr(ubi, vid_hdr);	}	err = ubi_io_read_data(ubi, buf, pnum, offset, len);	if (err) {		if (err == UBI_IO_BITFLIPS) {			scrub = 1;			err = 0;		} else if (err == -EBADMSG) {			if (vol->vol_type == UBI_DYNAMIC_VOLUME)				goto out_unlock;			scrub = 1;			if (!check) {				ubi_msg("force data checking");				check = 1;				goto retry;			}		} else			goto out_unlock;	}	if (check) {		uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len);		if (crc1 != crc) {			ubi_warn("CRC error: calculated %#08x, must be %#08x",				 crc1, crc);			err = -EBADMSG;			goto out_unlock;		}	}	if (scrub)		err = ubi_wl_scrub_peb(ubi, pnum);	leb_read_unlock(ubi, vol_id, lnum);	return err;out_free:	ubi_free_vid_hdr(ubi, vid_hdr);out_unlock:	leb_read_unlock(ubi, vol_id, lnum);	return err;}/** * recover_peb - recover from write failure. * @ubi: UBI device description object * @pnum: the physical eraseblock to recover * @vol_id: volume ID * @lnum: logical eraseblock number * @buf: data which was not written because of the write failure * @offset: offset of the failed write * @len: how many bytes should have been written * * This function is called in case of a write failure and moves all good data * from the potentially bad physical eraseblock to a good physical eraseblock. * This function also writes the data which was not written due to the failure. * Returns new physical eraseblock number in case of success, and a negative * error code in case of failure. */static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,		       const void *buf, int offset, int len){	int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;	struct ubi_volume *vol = ubi->volumes[idx];	struct ubi_vid_hdr *vid_hdr;	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);	if (!vid_hdr)		return -ENOMEM;	mutex_lock(&ubi->buf_mutex);retry:	new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);	if (new_pnum < 0) {		mutex_unlock(&ubi->buf_mutex);		ubi_free_vid_hdr(ubi, vid_hdr);		return new_pnum;	}	ubi_msg("recover PEB %d, move data to PEB %d", pnum, new_pnum);	err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);	if (err && err != UBI_IO_BITFLIPS) {		if (err > 0)			err = -EIO;		goto out_put;	}	vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));	err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);	if (err)		goto write_error;	data_size = offset + len;	memset(ubi->peb_buf1 + offset, 0xFF, len);	/* Read everything before the area where the write failure happened */	if (offset > 0) {		err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);		if (err && err != UBI_IO_BITFLIPS)			goto out_put;	}	memcpy(ubi->peb_buf1 + offset, buf, len);	err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);	if (err)		goto write_error;	mutex_unlock(&ubi->buf_mutex);	ubi_free_vid_hdr(ubi, vid_hdr);	vol->eba_tbl[lnum] = new_pnum;	ubi_wl_put_peb(ubi, pnum, 1);	ubi_msg("data was successfully recovered");	return 0;out_put:	mutex_unlock(&ubi->buf_mutex);	ubi_wl_put_peb(ubi, new_pnum, 1);	ubi_free_vid_hdr(ubi, vid_hdr);	return err;write_error:	/*	 * Bad luck? This physical eraseblock is bad too? Crud. Let's try to	 * get another one.	 */	ubi_warn("failed to write to PEB %d", new_pnum);	ubi_wl_put_peb(ubi, new_pnum, 1);	if (++tries > UBI_IO_RETRIES) {		mutex_unlock(&ubi->buf_mutex);		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}	ubi_msg("try again");	goto retry;}/** * ubi_eba_write_leb - write data to dynamic volume. * @ubi: UBI device description object * @vol: volume description object * @lnum: logical eraseblock number * @buf: the data to write * @offset: offset within the logical eraseblock where to write * @len: how many bytes to write * @dtype: data type * * This function writes data to logical eraseblock @lnum of a dynamic volume * @vol. Returns zero in case of success and a negative error code in case * of failure. In case of error, it is possible that something was still * written to the flash media, but may be some garbage. */int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,		      const void *buf, int offset, int len, int dtype){	int err, pnum, tries = 0, vol_id = vol->vol_id;	struct ubi_vid_hdr *vid_hdr;	if (ubi->ro_mode)		return -EROFS;	err = leb_write_lock(ubi, vol_id, lnum);	if (err)		return err;	pnum = vol->eba_tbl[lnum];	if (pnum >= 0) {		dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d",			len, offset, vol_id, lnum, pnum);		err = ubi_io_write_data(ubi, buf, pnum, offset, len);		if (err) {			ubi_warn("failed to write data to PEB %d", pnum);			if (err == -EIO && ubi->bad_allowed)				err = recover_peb(ubi, pnum, vol_id, lnum, buf,						  offset, len);			if (err)				ubi_ro_mode(ubi);		}		leb_write_unlock(ubi, vol_id, lnum);		return err;	}	/*	 * The logical eraseblock is not mapped. We have to get a free physical	 * eraseblock and write the volume identifier header there first.	 */	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);	if (!vid_hdr) {		leb_write_unlock(ubi, vol_id, lnum);		return -ENOMEM;	}	vid_hdr->vol_type = UBI_VID_DYNAMIC;	vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));	vid_hdr->vol_id = cpu_to_be32(vol_id);	vid_hdr->lnum = cpu_to_be32(lnum);	vid_hdr->compat = ubi_get_compat(ubi, vol_id);	vid_hdr->data_pad = cpu_to_be32(vol->data_pad);retry:	pnum = ubi_wl_get_peb(ubi, dtype);	if (pnum < 0) {		ubi_free_vid_hdr(ubi, vid_hdr);		leb_write_unlock(ubi, vol_id, lnum);		return pnum;	}	dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d",		len, offset, vol_id, lnum, pnum);	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);	if (err) {		ubi_warn("failed to write VID header to LEB %d:%d, PEB %d",			 vol_id, lnum, pnum);		goto write_error;	}	if (len) {		err = ubi_io_write_data(ubi, buf, pnum, offset, len);		if (err) {			ubi_warn("failed to write %d bytes at offset %d of "				 "LEB %d:%d, PEB %d", len, offset, vol_id,				 lnum, pnum);			goto write_error;		}	}	vol->eba_tbl[lnum] = pnum;	leb_write_unlock(ubi, vol_id, lnum);	ubi_free_vid_hdr(ubi, vid_hdr);	return 0;write_error:	if (err != -EIO || !ubi->bad_allowed) {		ubi_ro_mode(ubi);		leb_write_unlock(ubi, vol_id, lnum);		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}	/*	 * Fortunately, this is the first write operation to this physical	 * eraseblock, so just put it and request a new one. We assume that if	 * this physical eraseblock went bad, the erase code will handle that.	 */	err = ubi_wl_put_peb(ubi, pnum, 1);	if (err || ++tries > UBI_IO_RETRIES) {		ubi_ro_mode(ubi);		leb_write_unlock(ubi, vol_id, lnum);		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}	vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));	ubi_msg("try another PEB");	goto retry;}/** * ubi_eba_write_leb_st - write data to static volume. * @ubi: UBI device description object * @vol: volume description object * @lnum: logical eraseblock number * @buf: data to write * @len: how many bytes to write * @dtype: data type * @used_ebs: how many logical eraseblocks will this volume contain * * This function writes data to logical eraseblock @lnum of static volume * @vol. The @used_ebs argument should contain total number of logical * eraseblock in this static volume. * * When writing to the last logical eraseblock, the @len argument doesn't have * to be aligned to the minimal I/O unit size. Instead, it has to be equivalent * to the real data size, although the @buf buffer has to contain the * alignment. In all other cases, @len has to be aligned. * * It is prohibited to write more then once to logical eraseblocks of static * volumes. This function returns zero in case of success and a negative error * code in case of failure. */int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,			 int lnum, const void *buf, int len, int dtype,			 int used_ebs){	int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;	struct ubi_vid_hdr *vid_hdr;	uint32_t crc;	if (ubi->ro_mode)		return -EROFS;	if (lnum == used_ebs - 1)		/* If this is the last LEB @len may be unaligned */		len = ALIGN(data_size, ubi->min_io_size);	else		ubi_assert(!(len & (ubi->min_io_size - 1)));	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);	if (!vid_hdr)		return -ENOMEM;	err = leb_write_lock(ubi, vol_id, lnum);	if (err) {		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}	vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));	vid_hdr->vol_id = cpu_to_be32(vol_id);	vid_hdr->lnum = cpu_to_be32(lnum);	vid_hdr->compat = ubi_get_compat(ubi, vol_id);	vid_hdr->data_pad = cpu_to_be32(vol->data_pad);	crc = crc32(UBI_CRC32_INIT, buf, data_size);	vid_hdr->vol_type = UBI_VID_STATIC;	vid_hdr->data_size = cpu_to_be32(data_size);	vid_hdr->used_ebs = cpu_to_be32(used_ebs);	vid_hdr->data_crc = cpu_to_be32(crc);retry:	pnum = ubi_wl_get_peb(ubi, dtype);	if (pnum < 0) {		ubi_free_vid_hdr(ubi, vid_hdr);		leb_write_unlock(ubi, vol_id, lnum);		return pnum;	}	dbg_eba("write VID hdr and %d bytes at LEB %d:%d, PEB %d, used_ebs %d",		len, vol_id, lnum, pnum, used_ebs);	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);	if (err) {		ubi_warn("failed to write VID header to LEB %d:%d, PEB %d",			 vol_id, lnum, pnum);		goto write_error;	}	err = ubi_io_write_data(ubi, buf, pnum, 0, len);	if (err) {		ubi_warn("failed to write %d bytes of data to PEB %d",			 len, pnum);		goto write_error;	}	ubi_assert(vol->eba_tbl[lnum] < 0);	vol->eba_tbl[lnum] = pnum;	leb_write_unlock(ubi, vol_id, lnum);	ubi_free_vid_hdr(ubi, vid_hdr);	return 0;write_error:	if (err != -EIO || !ubi->bad_allowed) {		/*		 * This flash device does not admit of bad eraseblocks or		 * something nasty and unexpected happened. Switch to read-only		 * mode just in case.		 */		ubi_ro_mode(ubi);		leb_write_unlock(ubi, vol_id, lnum);		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}	err = ubi_wl_put_peb(ubi, pnum, 1);	if (err || ++tries > UBI_IO_RETRIES) {		ubi_ro_mode(ubi);		leb_write_unlock(ubi, vol_id, lnum);		ubi_free_vid_hdr(ubi, vid_hdr);		return err;	}

⌨️ 快捷键说明

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