All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
@ 2016-02-02  2:30 Bean Huo
  2016-02-02  2:30 ` [PATCH v2 01/17] include:mtd:add multi-plane page program command Bean Huo
                   ` (17 more replies)
  0 siblings, 18 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: BeanHuo <beanhuo@micron.com>

These patches aim to solve MLC NAND paired page power loss
issue,by adding a bakvol(backup volume) module in UBI layer.

MLC NAND paired page power loss issue is a known issue so far,
MLC NAND pages are coupled in a sense that if you cut power
while writing to a page, you corrupt not only this page, but
also one of the previous pages which is paired with the current
one.
http://www.linux-mtd.infradead.org/doc/ubifs.html#L_ubifs_mlc

This paired page power loss solution is based on NAND multiple
plane program feature. Dual plane page program method can program
two different plane pages at the same time. as for this solution,
there are three main steps:

1. initialization
 While UBI attach process, if ubi first attach MTD to ubi device,
bakvol will be created, and reserve 20 PEBs for bakvol. if not,
scan every PEB to find out bakvol PEB, update a bakvol PEB table
in RAM.
2. recovery
 While UBIFS mount, and if there is a power loss, bakvol module will
 check if there are lower pages being dameged by last power loss, if
 yes, bakvol will apply for one new PEB, move uncorrupted data to this
 PEB, and recover dameged data by backup page data in bakvol PEB.
3. backup
if UBI proggrams one lower page, bakvol module will duplicate this lower
page data,and then program source page data and backup page data into two
different plane pages(one is user data volume and another is backup volume)
at the same time through dual plane program command.
If UBI porgrams upper page data, still uses mtd_write() to program. In
another word, backup only implements while program lower page.

These patches have already been tested on Micron 70s/80s MLC NAND.

Any suggestions and comments welcomed.

This version patches based on Linux kernel 4.2-rc7.
 
 v2:
   1.Add CRC32 protection for user OOB area data.
   2.Move recovery action from attach step to ubifs mount step.
   3.Add more comments for some key function.
   4.standard multi-plane program function.
   5.Standard send-mail patches

Bean Huo (17):
  include:mtd:add multi-plane page program command
  include:mtd:add multi-plane program in mtd_info
  drivers:mtd:add multi-plane page program support in partition layer
  drivers:mtd:nand:enable dual plane page program function
  drivers:mtd:ubi:add bakvol on-flash and RAM data structures
  drivers:mtd:ubi:add bakvol function define in ubi layer
  fs:ubifs:add bakvol function define in ubifs layer
  drivers:mtd:ubi:disable bakvol function while writing volume table
  drivers:mtd:ubi:get PEB according to specfied plane number
  drivers:mtd:ubi:enable bakvol function for fastmap operation
  drivers:mtd:ubi:add disable/enable bakvol while ubi write
  drivers:mtd:ubi:add disable bakvol while ubi detach
  drivers:mtd:ubi:add bakvol init while attach ubi
  drivers:mtd:ubi:add backup operation in ubi_io_write
  fs:ubifs:enable bakvol module and  recover operation
  driver:mtd:ubi:add new bakvol module in ubi layer
  drivers:mtd:ubi: Kconfig Makefile

 drivers/mtd/mtdpart.c        |   19 +
 drivers/mtd/nand/nand_base.c |  405 +++++++++++++
 drivers/mtd/ubi/Kconfig      |   15 +
 drivers/mtd/ubi/Makefile     |    2 +-
 drivers/mtd/ubi/attach.c     |   24 +-
 drivers/mtd/ubi/bakvol.c     | 1296 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/ubi/build.c      |    2 +
 drivers/mtd/ubi/eba.c        |   13 +-
 drivers/mtd/ubi/fastmap.c    |    2 +-
 drivers/mtd/ubi/io.c         |   73 ++-
 drivers/mtd/ubi/ubi-media.h  |   64 +++
 drivers/mtd/ubi/ubi.h        |   23 +-
 drivers/mtd/ubi/vtbl.c       |    2 +-
 drivers/mtd/ubi/wl.c         |  140 +++++
 fs/ubifs/super.c             |   11 +
 fs/ubifs/ubifs.h             |    2 +
 include/linux/mtd/mtd.h      |   19 +
 include/linux/mtd/nand.h     |    4 +
 18 files changed, 2091 insertions(+), 25 deletions(-)
 create mode 100644 drivers/mtd/ubi/bakvol.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 01/17] include:mtd:add multi-plane page program command
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 02/17] include:mtd:add multi-plane program in mtd_info Bean Huo
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This patch file is to add multi-plane page program command,
and add dual plane page program hook pinter in nand_chip structure.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 include/linux/mtd/nand.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 272f429..4c5be01 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -77,6 +77,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_CMD_READ1		1
 #define NAND_CMD_RNDOUT		5
 #define NAND_CMD_PAGEPROG	0x10
+#define NAND_CMD_MULTI_PAGEPROG	0x11
 #define NAND_CMD_READOOB	0x50
 #define NAND_CMD_ERASE1		0x60
 #define NAND_CMD_STATUS		0x70
@@ -671,6 +672,9 @@ struct nand_chip {
 	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t offset, int data_len, const uint8_t *buf,
 			int oob_required, int page, int cached, int raw);
+	int (*write_plane_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t offset, int data_len, const uint8_t *buf,
+			int oob_required, int page, int plane, int raw);
 	int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
 			int feature_addr, uint8_t *subfeature_para);
 	int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 02/17] include:mtd:add multi-plane program in mtd_info
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
  2016-02-02  2:30 ` [PATCH v2 01/17] include:mtd:add multi-plane page program command Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer Bean Huo
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This patch file is to add support for multi-plane page program hook in mtd_info,
callback this in one new inline function mtd_write_dual_plane_oob.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 include/linux/mtd/mtd.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index f17fa75..cfcb3a68 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -204,6 +204,9 @@ struct mtd_info {
 			  struct mtd_oob_ops *ops);
 	int (*_write_oob) (struct mtd_info *mtd, loff_t to,
 			   struct mtd_oob_ops *ops);
+	int (*_dual_plane_write_oob) (struct mtd_info *mtd, loff_t to_plane0,
+			struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+					struct mtd_oob_ops *ops_plane1);
 	int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
 				    size_t *retlen, struct otp_info *buf);
 	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
@@ -280,6 +283,22 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	return mtd->_write_oob(mtd, to, ops);
 }
 
+static inline int mtd_write_dual_plane_oob(struct mtd_info *mtd,
+		loff_t to_plane0, struct mtd_oob_ops *ops0, loff_t to_plane1,
+						struct mtd_oob_ops *ops1)
+{
+	ops0->retlen = ops0->oobretlen = 0;
+	ops1->retlen = ops1->oobretlen = 0;
+
+	if (!mtd->_dual_plane_write_oob)
+		return -EOPNOTSUPP;
+	if (!(mtd->flags & MTD_WRITEABLE))
+		return -EROFS;
+
+	return mtd->_dual_plane_write_oob(mtd, to_plane0, ops0,
+						to_plane1, ops1);
+}
+
 int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf);
 int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
  2016-02-02  2:30 ` [PATCH v2 01/17] include:mtd:add multi-plane page program command Bean Huo
  2016-02-02  2:30 ` [PATCH v2 02/17] include:mtd:add multi-plane program in mtd_info Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  3:00   ` kbuild test robot
  2016-02-02  2:30 ` [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function Bean Huo
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file patch is to add multi-plane page program function in MTD partition layer and
call back MTD master dual plane page program function.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/mtdpart.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index cafdb88..85f68d0 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -203,6 +203,23 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
 	return part->master->_write_oob(part->master, to + part->offset, ops);
 }
 
+static int part_write_dual_plane_oob(struct mtd_info *mtd, loff_t to_plane0,
+			    struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			    struct mtd_oob_ops *ops_plane1)
+{
+	struct mtd_part *part = PART(mtd);
+
+	if ((to_plane0 >= mtd->size) || ((to_plane1 >= mtd->size)))
+		return -EINVAL;
+	if ((ops_plane0->datbuf && to_plane0 + ops_plane0->len > mtd->size) ||
+	    (ops_plane1->datbuf && to_plane1 + ops_plane0->len > mtd->size))
+		return -EINVAL;
+
+	return part->master->_dual_plane_write_oob(part->master,
+				to_plane0 + part->offset, ops_plane0,
+				to_plane1 + part->offset, ops_plane1);
+}
+
 static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
 		size_t len, size_t *retlen, u_char *buf)
 {
@@ -409,6 +426,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
 		slave->mtd._read_oob = part_read_oob;
 	if (master->_write_oob)
 		slave->mtd._write_oob = part_write_oob;
+	if (master->_dual_plane_write_oob)
+		slave->mtd._dual_plane_write_oob = part_write_dual_plane_oob;
 	if (master->_read_user_prot_reg)
 		slave->mtd._read_user_prot_reg = part_read_user_prot_reg;
 	if (master->_read_fact_prot_reg)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (2 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  3:04   ` kbuild test robot
  2016-02-02  2:30 ` [PATCH v2 05/17] drivers:mtd:ubi:add bakvol on-flash and RAM data structures Bean Huo
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

The PROGRAM PAGE MULTI-PLANE (80h-11h) command enables
the host to input data to the addressed plane's cache register
and queue the cache register to ultimately be moved to the
NAND Flash array. This command can be issued one or more times.
Each time a new plane address is specified that plane is also
queued for data transfer. To input data for the final plane and
to begin the program operation for all previously queued planes,
issue either the PROGRAM PAGE (80h-10h) command or the PROGRAM
PAGE CACHE (80h-15h) command. All of the queued planes will move
the data to the NAND Flash array.

For this version patches, currently, only support dual plane page program.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/nand/nand_base.c | 405 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 405 insertions(+)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ceb68ca..b5cbd0a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2249,6 +2249,75 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
 
 	return 0;
 }
+/**
+ * nand_write_plane_page - [REPLACEABLE] write one page
+ * @mtd: MTD device structure
+ * @chip: NAND chip descriptor
+ * @offset: address offset within the page
+ * @data_len: length of actual data to be written
+ * @buf: the data to write
+ * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
+ * @plane: multiple plane programming
+ * @raw: use _raw version of write_page
+ */
+static int nand_write_plane_page(struct mtd_info *mtd, struct nand_chip *chip,
+			    uint32_t offset, int data_len, const uint8_t *buf,
+			    int oob_required, int page, int plane, int raw)
+{
+	int status, subpage;
+
+	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+	    chip->ecc.write_subpage)
+		subpage = offset || (data_len < mtd->writesize);
+	else
+		subpage = 0;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+	if (unlikely(raw))
+		status = chip->ecc.write_page_raw(mtd, chip, buf,
+							oob_required);
+	else if (subpage)
+		status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
+							buf, oob_required);
+	else
+		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+	if (status < 0)
+		return status;
+
+	/* Multipal plane progamming */
+	if (plane) {
+		chip->cmdfunc(mtd, NAND_CMD_MULTI_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available.
+		 */
+	    if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+	    if (status & NAND_STATUS_FAIL)
+		return -EIO;
+
+	} else if (!plane || !NAND_HAS_CACHEPROG(chip)) {
+
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available.
+		 */
+	    if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+	    if (status & NAND_STATUS_FAIL)
+		return -EIO;
+	}
+
+	return 0;
+}
 
 /**
  * nand_write_page - [REPLACEABLE] write one page
@@ -2373,6 +2442,277 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 }
 
 #define NOTALIGNED(x)	((x & (chip->subpagesize - 1)) != 0)
+/**
+ * nand_do_dual_plane_write_ops - [INTERN] NAND write with ECC by dual plane
+ * @mtd: MTD device structure
+ * @to_plane0: offset of  write plane 0
+ * @ops_plane0: oob operations description structure for plane 0
+ * @to_plane1: offset of  write plane 1
+ * @ops_plane1: oob operations description structure for plane 1
+ *
+ * NAND write with ECC through dual plane program.
+ */
+static int nand_do_dual_plane_write_ops(struct mtd_info *mtd, loff_t to_plane0,
+			   struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			   struct mtd_oob_ops *ops_plane1)
+{
+	int chipnr0, chipnr1, chipnr = 0, blockmask;
+	uint32_t oobwritelen = 0;
+	uint32_t oobmaxlen = 0;
+	int ret;
+	int column = 0, realpage = 0, page = 0;
+	uint32_t writelen = 0;
+	char flag = 0, cycle = 0;
+	int oob_required = 0;
+	uint8_t *oob = NULL;
+	uint8_t *buf = NULL;
+	uint32_t bak0_oobwritelen = 0, bak1_oobwritelen = 0;
+	int bak0_column = 0, bak1_column = 0;
+	int bak0_realpage = 0, bak1_realpage = 0;
+	int bak0_page = 0, bak1_page = 0;
+	int bak0_writelen = 0, bak1_writelen = 0;
+	uint8_t *bak0_buf = NULL, *bak1_buf = NULL;
+	uint8_t *bak0_oob = NULL, *bak1_oob = NULL;
+	uint8_t bak0_pagebuf = 0, bak1_pagebuf = 0;
+	int bytes = 0;
+	int cached = 0;
+	uint8_t *wbuf = NULL;
+	int use_bufpoi = 0;
+	int part_pagewr = 0;
+	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops *ops = NULL;
+
+	ops_plane0->retlen = 0;
+	ops_plane1->retlen = 0;
+
+	if ((!ops_plane0->len) || (!ops_plane1->len))
+		return 0;
+
+	/* Reject writes, which are not page aligned */
+	if (NOTALIGNED(to_plane0) || NOTALIGNED(ops_plane0->len) ||
+	    NOTALIGNED(to_plane1) || NOTALIGNED(ops_plane1->len)) {
+		pr_notice("%s: attempt to write non page aligned data\n",
+								__func__);
+		return -EINVAL;
+	}
+
+	chipnr0 = (int)(to_plane0 >> chip->chip_shift);
+	chipnr1 = (int)(to_plane1 >> chip->chip_shift);
+
+	if (unlikely(chipnr0 != chipnr1)) {
+		pr_notice("%s: attempt to write different nand chip\n",
+								__func__);
+		return -EINVAL;
+	}
+
+	chip->select_chip(mtd, chipnr0);
+
+	/* Check, if it is write protected */
+	if (nand_check_wp(mtd)) {
+		ret = -EIO;
+		goto err_out;
+	}
+
+	blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+
+	/* Don't allow multipage oob writes with offset */
+	if ((ops_plane0->oobbuf && ops_plane0->ooboffs &&
+	(ops_plane0->ooboffs + ops_plane0->ooblen > oobmaxlen)) ||
+	(ops_plane1->oobbuf && ops_plane1->ooboffs &&
+	(ops_plane1->ooboffs + ops_plane1->ooblen > oobmaxlen))) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	while (1) {
+retry:
+		if (flag == 0) {
+			/* operate plane 0 */
+			ops = ops_plane0;
+			oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
+					mtd->oobavail : mtd->oobsize;
+			chipnr = chipnr0;
+			oob_required = ops->oobbuf ? 1 : 0;
+
+		   if (cycle == 0) {
+			/* plane 0 first write,backup programming infor */
+			bak0_oobwritelen = oobwritelen = ops->ooblen;
+			bak0_column = column = to_plane0 & (mtd->writesize - 1);
+			realpage = (int)(to_plane0 >> chip->page_shift);
+			bak0_realpage = realpage;
+			bak0_page = page = realpage & chip->pagemask;
+			bak0_writelen = writelen = ops->len;
+			bak0_buf = buf = ops->datbuf;
+			bak0_oob = oob = ops->oobbuf;
+
+		if (to_plane0 <= ((loff_t)chip->pagebuf << chip->page_shift) &&
+	   ((loff_t)chip->pagebuf << chip->page_shift) < (to_plane0 + ops->len))
+				chip->pagebuf = -1;
+
+			bak0_pagebuf = chip->pagebuf;
+
+		   } else {
+			oobwritelen = bak0_oobwritelen;
+			column = bak0_column;
+			realpage = bak0_realpage;
+			page = bak0_page;
+			writelen = bak0_writelen;
+			buf = bak0_buf;
+			oob = bak0_oob;
+			chip->pagebuf  = bak0_pagebuf;
+		   }
+		} else if (flag == 1) {
+			/* operate plane 1 */
+			ops = ops_plane1;
+			oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
+					mtd->oobavail : mtd->oobsize;
+			chipnr = chipnr1;
+			oob_required = ops->oobbuf ? 1 : 0;
+
+		   if (cycle == 0) {
+			/* plane 1 first write,backup programming infor */
+			bak1_oobwritelen = oobwritelen = ops->ooblen;
+			bak1_column = column = to_plane1 & (mtd->writesize - 1);
+			realpage = (int)(to_plane1 >> chip->page_shift);
+			bak1_realpage = realpage;
+			bak1_page = page = realpage & chip->pagemask;
+			bak1_writelen = writelen = ops->len;
+			bak1_buf = buf = ops->datbuf;
+			bak1_oob = oob = ops->oobbuf;
+
+	      if (to_plane1 <= ((loff_t)chip->pagebuf << chip->page_shift) &&
+	   ((loff_t)chip->pagebuf << chip->page_shift) < (to_plane1 + ops->len))
+				chip->pagebuf = -1;
+
+			bak1_pagebuf = chip->pagebuf;
+			} else {
+			oobwritelen = bak1_oobwritelen;
+			column = bak1_column;
+			realpage = bak1_realpage;
+			page = bak1_page;
+			writelen = bak1_writelen;
+			buf = bak1_buf;
+			oob = bak1_oob;
+			chip->pagebuf  = bak1_pagebuf;
+			}
+		}
+
+		/* Don't allow multipage oob writes with offset */
+		if (ops->oobbuf && ops->ooboffs &&
+			(ops->ooboffs + ops->ooblen > oobmaxlen)) {
+			ret = -EINVAL;
+			goto err_out;
+		}
+
+		bytes = mtd->writesize;
+		cached = writelen > bytes && page != blockmask;
+		wbuf = buf;
+
+		part_pagewr = (column || writelen < (mtd->writesize - 1));
+
+		if (part_pagewr)
+			use_bufpoi = 1;
+		else if (chip->options & NAND_USE_BOUNCE_BUFFER)
+			use_bufpoi = !virt_addr_valid(buf);
+		else
+			use_bufpoi = 0;
+
+		/* Partial page write?, or need to use bounce buffer */
+		if (use_bufpoi) {
+			pr_debug("%s: using write bounce buffer for buf@%p\n",
+								__func__, buf);
+			cached = 0;
+			if (part_pagewr)
+				bytes = min_t(int, bytes - column, writelen);
+			chip->pagebuf = -1;
+			memset(chip->buffers->databuf, 0xff, mtd->writesize);
+			memcpy(&chip->buffers->databuf[column], buf, bytes);
+			wbuf = chip->buffers->databuf;
+		}
+
+		if (unlikely(oob)) {
+			size_t len = min(oobwritelen, oobmaxlen);
+
+			oob = nand_fill_oob(mtd, oob, len, ops);
+			oobwritelen -= len;
+		} else {
+			/* We still need to erase leftover OOB data */
+			memset(chip->oob_poi, 0xff, mtd->oobsize);
+		}
+
+		if (flag == 0) {
+			ret = chip->write_plane_page(mtd, chip, column, bytes,
+		      wbuf, oob_required, page, 1, (ops->mode == MTD_OPS_RAW));
+		} else if (flag == 1) {
+			ret = chip->write_page(mtd, chip, column, bytes, wbuf,
+			oob_required, page, cached, (ops->mode == MTD_OPS_RAW));
+		}
+
+		if (ret)
+			break;
+
+		writelen -= bytes;
+		column = 0;
+
+		if (flag == 0) {
+			bak0_writelen = writelen;
+			bak0_column = column;
+			bak0_oobwritelen = oobwritelen;
+		} else {
+			bak1_writelen = writelen;
+			bak1_column = column;
+			bak1_oobwritelen = oobwritelen;
+		}
+
+		if ((!writelen) && (flag == 1))
+			break;
+
+		buf += bytes;
+		realpage++;
+
+		if (flag == 0) {
+			bak0_buf = buf;
+			bak0_oob = oob;
+			bak0_realpage = realpage;
+		} else {
+			bak1_buf = buf;
+			bak1_oob = oob;
+			bak1_realpage = realpage;
+		}
+
+		if (flag == 0) {
+			flag = 1;
+		goto retry;
+		}
+
+		page = realpage & chip->pagemask;
+
+		/* Check, if we cross a chip boundary */
+		if (!page) {
+			chipnr++;
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
+		}
+
+		flag = 0;
+		cycle++;
+
+	}
+
+	ops_plane0->retlen = ops_plane0->len - bak0_writelen;
+	ops_plane1->retlen = ops_plane1->len - bak1_writelen;
+
+	if (unlikely(bak0_oob))
+		ops_plane0->oobretlen = ops_plane0->ooblen;
+	if (unlikely(bak1_oob))
+		ops_plane1->oobretlen = ops_plane1->ooblen;
+
+err_out:
+	flag = 0;
+	cycle = 0;
+	chip->select_chip(mtd, -1);
+	return ret;
+}
 
 /**
  * nand_do_write_ops - [INTERN] NAND write with ECC
@@ -2564,6 +2904,14 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 	return ret;
 }
 
+static int nand_do_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
+			      struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			      struct mtd_oob_ops *ops_plane1)
+{
+	return 0;
+
+}
+
 /**
  * nand_do_write_oob - [MTD Interface] NAND write out-of-band
  * @mtd: MTD device structure
@@ -2692,6 +3040,52 @@ out:
 	return ret;
 }
 
+static int nand_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
+			   struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			   struct mtd_oob_ops *ops_plane1)
+{
+	int ret = -ENOTSUPP;
+
+	/* Do not allow writes past end of device */
+	if ((ops_plane0->datbuf && (to_plane0 + ops_plane0->len) > mtd->size) ||
+	    (ops_plane1->datbuf && (to_plane1 + ops_plane1->len) > mtd->size)) {
+		pr_debug("%s: attempt to write beyond end of device\n",
+								__func__);
+		return -EINVAL;
+	}
+	nand_get_device(mtd, FL_WRITING);
+
+	switch (ops_plane0->mode) {
+	case MTD_OPS_PLACE_OOB:
+		if (ops_plane1->mode != MTD_OPS_PLACE_OOB)
+			goto out;
+		break;
+	case MTD_OPS_AUTO_OOB:
+		if (ops_plane1->mode != MTD_OPS_AUTO_OOB)
+			goto out;
+		break;
+	case MTD_OPS_RAW:
+		if (ops_plane1->mode != MTD_OPS_RAW)
+			goto out;
+		break;
+
+	default:
+		goto out;
+	}
+
+	if (!ops_plane0->datbuf && !ops_plane1->datbuf)
+		ret = nand_do_dual_plane_write_oob(mtd, to_plane0, ops_plane0,
+							to_plane1, ops_plane1);
+	else
+		ret = nand_do_dual_plane_write_ops(mtd, to_plane0, ops_plane0,
+							to_plane1, ops_plane1);
+
+out:
+	nand_release_device(mtd);
+	return ret;
+}
+EXPORT_SYMBOL(nand_dual_plane_write_oob);
+
 /**
  * single_erase - [GENERIC] NAND standard block erase command function
  * @mtd: MTD device structure
@@ -2764,6 +3158,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		goto erase_exit;
 	}
 
+
 	/* Loop through the pages */
 	len = instr->len;
 
@@ -2904,6 +3299,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
 		chip->write_byte(mtd, subfeature_param[i]);
 
+	if ((addr == ONFI_FEATURE_ADDR_TIMING_MODE) && ((subfeature_param[0]&0xF0) != 0))
+		return 0;
+
 	status = chip->waitfunc(mtd, chip);
 	if (status & NAND_STATUS_FAIL)
 		return -EIO;
@@ -3991,6 +4389,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 	if (!chip->write_page)
 		chip->write_page = nand_write_page;
+	if (!chip->write_plane_page)
+		chip->write_plane_page = nand_write_plane_page;
 
 	/*
 	 * Check ECC mode, default to software if 3byte/512byte hardware ECC is
@@ -4206,6 +4606,11 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->_panic_write = panic_nand_write;
 	mtd->_read_oob = nand_read_oob;
 	mtd->_write_oob = nand_write_oob;
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	mtd->_dual_plane_write_oob = nand_dual_plane_write_oob;
+#else
+	mtd->_dual_plane_write_oob = NULL;
+#endif
 	mtd->_sync = nand_sync;
 	mtd->_lock = NULL;
 	mtd->_unlock = NULL;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 05/17] drivers:mtd:ubi:add bakvol on-flash and RAM data structures
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (3 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer Bean Huo
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file is to add bakvol default configure and on-flash data structures.
Here add three key structures:
        ubi_bkblk_info: for backup block programming info.
        bakvol_oob_info: for user oob area bakvol data structure.
        ubi_bkblk_tbl: for bakvol module info.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/ubi-media.h | 64 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index d0d072e..8981a39 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -31,6 +31,7 @@
 #define __UBI_MEDIA_H__
 
 #include <asm/byteorder.h>
+#include <linux/list.h>
 
 /* The version of UBI images supported by this implementation */
 #define UBI_VERSION 1
@@ -295,7 +296,11 @@ struct ubi_vid_hdr {
 } __packed;
 
 /* Internal UBI volumes count */
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+#define UBI_INT_VOL_COUNT 2
+#else
 #define UBI_INT_VOL_COUNT 1
+#endif
 
 /*
  * Starting ID of internal volumes: 0x7fffefff.
@@ -312,6 +317,15 @@ struct ubi_vid_hdr {
 #define UBI_LAYOUT_VOLUME_NAME   "layout volume"
 #define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
 
+/* The backup log volume */
+
+#define UBI_BACKUP_VOLUME_ID     (UBI_INTERNAL_VOL_START + 1)
+#define UBI_BACKUP_VOLUME_TYPE   UBI_VID_DYNAMIC
+#define UBI_BACKUP_VOLUME_ALIGN  1
+#define UBI_BACKUP_VOLUME_EBS    20
+#define UBI_BACKUP_VOLUME_NAME   "bakvol"
+#define UBI_BACKUP_VOLUME_COMPAT UBI_COMPAT_REJECT
+
 /* The maximum number of volumes per one UBI device */
 #define UBI_MAX_VOLUMES 128
 
@@ -325,6 +339,56 @@ struct ubi_vid_hdr {
 #define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
 
 /**
+ * struct ubi_bkblk_info - the information for one backup block .
+ * @peb: physical block number
+ * @leb:  logic block number
+ * @plane: this block belongs to which plane
+ * @pgnum: the page number that already be programmed last time.
+ */
+struct ubi_bkblk_info {
+	__be32  peb;
+	__be32  leb;
+	__u8    plane;
+	__be32  pgnum;
+	struct  list_head node;
+}__packed;
+
+/**
+ * struct bakvol_oob_info - user oob area structure.
+ * @addr: address of source/backup page
+ * @crc: CRC-32 checksum of addr
+ *
+ */
+struct bakvol_oob_info {
+	loff_t addr;
+	__le32 crc;
+} __packed;
+
+/* Sizes of bakvol oob area */
+#define UBI_BAKVOL_OOB_SIZE sizeof(struct bakvol_oob_info)
+
+/* Sizes of bakvol oob area without the ending CRC */
+#define UBI_BAKVOL_OOB_SIZE_CRC (UBI_BAKVOL_OOB_SIZE - sizeof(__be32))
+
+/**
+ * struct ubi_bkblk_tbl - a table for backup blocks.
+ * @bakvol_flag: indicate if backup volume be initted
+ * @bcount_of_plane: block count that has bee applied for corresponding plane
+ * @head: the list of backup blocks.
+ */
+struct ubi_bkblk_tbl {
+	__u8    bakvol_flag;
+#define UBI_BAKVOL_INIT_START 0x01 /* init bakvol module start */
+#define UBI_BAKVOL_REJECT 0x02 /* reject bakvol module operations */
+#define UBI_BAKVOL_INIT_DONE 0x04 /* init bakvol module done */
+#define UBI_BAKVOL_ENABLE 0x08 /* enable bakvol module */
+#define UBI_BAKVOL_DISABLE 0x10 /* disable bakvol module */
+#define UBI_BAKVOL_RECOVERY 0x20 /* bakvol recovery already done */
+	__be32  bcount_of_plane[2];
+	struct  list_head head;
+}__packed;;
+
+/**
  * struct ubi_vtbl_record - a record in the volume table.
  * @reserved_pebs: how many physical eraseblocks are reserved for this volume
  * @alignment: volume alignment
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (4 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 05/17] drivers:mtd:ubi:add bakvol on-flash and RAM data structures Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  3:05   ` kbuild test robot
  2016-02-02  3:08   ` kbuild test robot
  2016-02-02  2:30 ` [PATCH v2 07/17] fs:ubifs:add bakvol function define in ubifs layer Bean Huo
                   ` (11 subsequent siblings)
  17 siblings, 2 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file patch is to add bakvol function define in ubi layer and
add bakvol point in ubi_device structure. Add one new parameter for ubi layer write
function, in order to indicate if this time programming data should be protected.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/ubi.h | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 2974b67..4a80359 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -438,6 +438,7 @@ struct ubi_debug_info {
  * @vtbl_slots: how many slots are available in the volume table
  * @vtbl_size: size of the volume table in bytes
  * @vtbl: in-RAM volume table copy
+ * @bkblk_tbl: backup block table
  * @device_mutex: protects on-flash volume table and serializes volume
  *                creation, deletion, update, re-size, re-name and set
  *                property
@@ -547,6 +548,7 @@ struct ubi_device {
 	int vtbl_slots;
 	int vtbl_size;
 	struct ubi_vtbl_record *vtbl;
+	struct ubi_bkblk_tbl *bkblk_tbl;
 	struct mutex device_mutex;
 
 	int max_ec;
@@ -797,6 +799,20 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
 			    struct list_head *rename_list);
 int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai);
 
+/* bakvol.c*/
+int ubi_check_bakvol_module(struct ubi_device *ubi);
+int ubi_duplicate_data_to_bakvol(struct ubi_device *ubi, loff_t addr,
+		size_t len, size_t *retlen, const void *buf);
+int ubi_bakvol_module_init(struct ubi_device *ubi);
+int ubi_bakvol_peb_scan(struct ubi_device *ubi,
+			struct ubi_vid_hdr *vidh, int pnum);
+int ubi_bakvol_module_init_tail(struct ubi_device *ubi,
+				struct ubi_attach_info *si);
+int ubi_corrupted_data_recovery(struct ubi_volume_desc *desc);
+int is_backup_need(struct ubi_device *ubi, loff_t addr);
+void init_bakvol(struct ubi_volume_desc *desc, uint8_t choice);
+void clear_bakvol(struct ubi_device *ubi);
+
 /* vmt.c */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
 int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl);
@@ -846,6 +862,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
 
 /* wl.c */
 int ubi_wl_get_peb(struct ubi_device *ubi);
+int ubi_wl_get_plane_peb(struct ubi_device *ubi, int plane);
 int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
 		   int pnum, int torture);
 int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum);
@@ -864,7 +881,7 @@ int ubi_ensure_anchor_pebs(struct ubi_device *ubi);
 int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
 		int len);
 int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
-		 int len);
+		 int len, int safeguard);
 int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture);
 int ubi_io_is_bad(const struct ubi_device *ubi, int pnum);
 int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum);
@@ -1054,10 +1071,10 @@ static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
  * physical eraseblock.
  */
 static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
-				    int pnum, int offset, int len)
+				    int pnum, int offset, int len, int safeguard)
 {
 	ubi_assert(offset >= 0);
-	return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len);
+	return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len, safeguard);
 }
 
 /**
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 07/17] fs:ubifs:add bakvol function define in ubifs layer
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (5 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 08/17] drivers:mtd:ubi:disable bakvol function while writing volume table Bean Huo
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file patch is to add bakvol function define that
will be called in ubifs layer.
Here has two functions will be called:
	init_bakvol() disable or enable bakvol module.
	ubi_corrupted_data_recovery() recover corrupted page data.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 fs/ubifs/ubifs.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index de75902..92bebaa 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1479,6 +1479,8 @@ extern const struct inode_operations ubifs_dir_inode_operations;
 extern const struct inode_operations ubifs_symlink_inode_operations;
 extern struct backing_dev_info ubifs_backing_dev_info;
 extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
+extern void init_bakvol(struct ubi_volume_desc *desc, uint8_t choice);
+extern int ubi_corrupted_data_recovery(struct ubi_volume_desc *desc);
 
 /* io.c */
 void ubifs_ro_mode(struct ubifs_info *c, int err);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 08/17] drivers:mtd:ubi:disable bakvol function while writing volume table
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (6 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 07/17] fs:ubifs:add bakvol function define in ubifs layer Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 09/17] drivers:mtd:ubi:get PEB according to specfied plane number Bean Huo
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file patch is to modify ubi_io_write_data() function,
and disable bakvol function while wirting volume table since
volume table is rarely modified.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/vtbl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 80bdd5b..6103f4e 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -329,7 +329,7 @@ retry:
 		goto write_error;
 
 	/* Write the layout volume contents */
-	err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size);
+	err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size, 0);
 	if (err)
 		goto write_error;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 09/17] drivers:mtd:ubi:get PEB according to specfied plane number
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (7 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 08/17] drivers:mtd:ubi:disable bakvol function while writing volume table Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 10/17] drivers:mtd:ubi:enable bakvol function for fastmap operation Bean Huo
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This patch is to add new functions in order to get one free PEB according
to specified plane number. Currently, bakvol only support parallel
nand with dual plane.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/wl.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 275d9fb..de8e348 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -140,6 +140,7 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
 				 struct ubi_wl_entry *e, struct rb_root *root);
 static int self_check_in_pq(const struct ubi_device *ubi,
 			    struct ubi_wl_entry *e);
+static int produce_free_peb(struct ubi_device *ubi);
 
 /**
  * wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -341,6 +342,47 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
 	return e;
 }
 
+static struct ubi_wl_entry *find_wl_plane_entry(struct ubi_device *ubi,
+				struct rb_root *root, int diff, int plane)
+{
+	struct rb_node *p;
+	struct ubi_wl_entry *e, *prev_e = NULL, *bk_e = NULL;
+	int max;
+
+	e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
+	max = e->ec + diff;
+
+	p = root->rb_node;
+	while (p) {
+		struct ubi_wl_entry *e1;
+
+		e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
+		if (e1->ec >= max)
+			p = p->rb_left;
+		else {
+			p = p->rb_right;
+			if (e->pnum%2 == plane)
+				prev_e = e;
+
+			e = e1;
+
+			if (e1->pnum%2 == plane)
+				bk_e = e1;
+		}
+	}
+
+	/**
+	*If no fastmap has been written and this WL entry can be used
+	* as anchor PEB, hold it back and return the second best WL entry
+	* such that fastmap can use the anchor PEB later.
+	**/
+	if (prev_e && !ubi->fm_disabled &&
+	    !ubi->fm && bk_e->pnum < UBI_FM_MAX_START)
+		return prev_e;
+
+	return bk_e;
+}
+
 /**
  * find_mean_wl_entry - find wear-leveling entry with medium erase counter.
  * @ubi: UBI device description object
@@ -371,6 +413,32 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi,
 	return e;
 }
 
+static struct ubi_wl_entry *find_mean_plane_wl_entry(struct ubi_device *ubi,
+						struct rb_root *root, int plane)
+{
+	struct ubi_wl_entry *e, *first, *last;
+	struct rb_node *rb;
+
+	rb = root->rb_node;
+	first = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
+	last = rb_entry(rb_last(root), struct ubi_wl_entry, u.rb);
+
+	if (last->ec - first->ec < WL_FREE_MAX_DIFF) {
+		/* Currently, bakvol doesn't support fastmap */
+		while (rb) {
+			e = rb_entry(rb, struct ubi_wl_entry, u.rb);
+			if (e->pnum%2 == plane)
+				break;
+			rb = rb_next(rb);
+		/* Only returns specified plane peb */
+			e = NULL;
+		}
+	} else
+		e = find_wl_plane_entry(ubi, root, WL_FREE_MAX_DIFF/2, plane);
+
+	return e;
+}
+
 /**
  * wl_get_wle - get a mean wl entry to be used by ubi_wl_get_peb() or
  * refill_wl_user_pool().
@@ -403,6 +471,38 @@ static struct ubi_wl_entry *wl_get_wle(struct ubi_device *ubi)
 }
 
 /**
+ * wl_get_wle_plane - get a mean wl entry to be used by ubi_wl_get_plane_peb() or
+ * refill_wl_user_pool().
+ * @ubi: UBI device description object
+ * @plane: plane number
+ *
+ * This function returns a a wear leveling entry in case of success and
+ * NULL in case of failure.
+ */
+static struct ubi_wl_entry *wl_get_plane_wle(struct ubi_device *ubi, int plane)
+{
+	struct ubi_wl_entry *e;
+
+	e = find_mean_plane_wl_entry(ubi, &ubi->free, plane);
+	if (!e) {
+		ubi_err(ubi, "get mean plane eraseblocks failed");
+		return NULL;
+	}
+
+	self_check_in_wl_tree(ubi, e, &ubi->free);
+
+	/*
+	 * Move the physical eraseblock to the protection queue where it will
+	 * be protected from being moved for some time.
+	 */
+	rb_erase(&e->u.rb, &ubi->free);
+	ubi->free_count--;
+	dbg_wl("PEB %d EC %d", e->pnum, e->ec);
+
+	return e;
+}
+
+/**
  * prot_queue_del - remove a physical eraseblock from the protection queue.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock to remove
@@ -1751,6 +1851,7 @@ static int self_check_in_pq(const struct ubi_device *ubi,
 	dump_stack();
 	return -EINVAL;
 }
+
 #ifndef CONFIG_MTD_UBI_FASTMAP
 static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 {
@@ -1839,6 +1940,45 @@ retry:
 
 	return e->pnum;
 }
+
+int ubi_wl_get_plane_peb(struct ubi_device *ubi, int plane)
+{
+	int err;
+	struct ubi_wl_entry *e;
+
+retry:
+	spin_lock(&ubi->wl_lock);
+	if (!ubi->free.rb_node) {
+		if (ubi->works_count == 0) {
+			ubi_err(ubi, "no free eraseblocks");
+			ubi_assert(list_empty(&ubi->works));
+			spin_unlock(&ubi->wl_lock);
+			return -ENOSPC;
+		}
+
+		err = produce_free_peb(ubi);
+		if (err < 0) {
+			spin_unlock(&ubi->wl_lock);
+			return err;
+		}
+		spin_unlock(&ubi->wl_lock);
+		goto retry;
+
+	}
+	e = wl_get_plane_wle(ubi, plane);
+	prot_queue_add(ubi, e);
+	spin_unlock(&ubi->wl_lock);
+
+	err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+				    ubi->peb_size - ubi->vid_hdr_aloffset);
+	if (err) {
+		ubi_err(ubi, "new PEB %d does not contain all 0xFF bytes", e->pnum);
+		return err;
+	}
+
+	return e->pnum;
+}
+
 #else
 #include "fastmap-wl.c"
 #endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 10/17] drivers:mtd:ubi:enable bakvol function for fastmap operation
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (8 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 09/17] drivers:mtd:ubi:get PEB according to specfied plane number Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 11/17] drivers:mtd:ubi:add disable/enable bakvol while ubi write Bean Huo
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/fastmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 4aa2fd8..d32148b 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1313,7 +1313,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
 
 	for (i = 0; i < new_fm->used_blocks; i++) {
 		ret = ubi_io_write(ubi, fm_raw + (i * ubi->leb_size),
-			new_fm->e[i]->pnum, ubi->leb_start, ubi->leb_size);
+			new_fm->e[i]->pnum, ubi->leb_start, ubi->leb_size, 1);
 		if (ret) {
 			ubi_err(ubi, "unable to write fastmap to PEB %i!",
 				new_fm->e[i]->pnum);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 11/17] drivers:mtd:ubi:add disable/enable bakvol while ubi write
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (9 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 10/17] drivers:mtd:ubi:enable bakvol function for fastmap operation Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 12/17] drivers:mtd:ubi:add disable bakvol while ubi detach Bean Huo
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This patch is to modify ubi write action, add disable/enable backup operation according
to data type. For EC header, VID header,master node,super block writing,
bakvol module will not backup these data into bakvol volume.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/eba.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 51bca03..0f1f8a5 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -604,7 +604,7 @@ retry:
 
 	memcpy(ubi->peb_buf + offset, buf, len);
 
-	err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
+	err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size, 0);
 	if (err) {
 		mutex_unlock(&ubi->buf_mutex);
 		up_read(&ubi->fm_eba_sem);
@@ -675,7 +675,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 		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);
+		err = ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
 		if (err) {
 			ubi_warn(ubi, "failed to write data to PEB %d", pnum);
 			if (err == -EIO && ubi->bad_allowed)
@@ -726,7 +726,7 @@ retry:
 	}
 
 	if (len) {
-		err = ubi_io_write_data(ubi, buf, pnum, offset, len);
+		err = ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
 		if (err) {
 			ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d",
 				 len, offset, vol_id, lnum, pnum);
@@ -848,7 +848,7 @@ retry:
 		goto write_error;
 	}
 
-	err = ubi_io_write_data(ubi, buf, pnum, 0, len);
+	err = ubi_io_write_data(ubi, buf, pnum, 0, len, ((lnum < 3) ? 0:1));
 	if (err) {
 		ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
 			 len, pnum);
@@ -968,7 +968,7 @@ retry:
 		goto write_error;
 	}
 
-	err = ubi_io_write_data(ubi, buf, pnum, 0, len);
+	err = ubi_io_write_data(ubi, buf, pnum, 0, len, ((lnum < 3) ? 0 : 1));
 	if (err) {
 		ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
 			 len, pnum);
@@ -1194,7 +1194,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
 	}
 
 	if (data_size > 0) {
-		err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size);
+		err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size,
+			((lnum < 3) ? 0 : 1));
 		if (err) {
 			if (err == -EIO)
 				err = MOVE_TARGET_WR_ERR;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 12/17] drivers:mtd:ubi:add disable bakvol while ubi detach
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (10 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 11/17] drivers:mtd:ubi:add disable/enable bakvol while ubi write Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 13/17] drivers:mtd:ubi:add bakvol init while attach ubi Bean Huo
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

When ubi device is detached, bakvol should be disable and free pre-allocation
memory.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/build.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 22fd19c..4f7a466 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1118,6 +1118,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	 */
 	get_device(&ubi->dev);
 
+	clear_bakvol(ubi);
+
 	ubi_debugfs_exit_dev(ubi);
 	uif_close(ubi);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 13/17] drivers:mtd:ubi:add bakvol init while attach ubi
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (11 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 12/17] drivers:mtd:ubi:add disable bakvol while ubi detach Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 14/17] drivers:mtd:ubi:add backup operation in ubi_io_write Bean Huo
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This file is to initial bakvol moduel and scan PEB to find
bakvol PEB while attach ubi device.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/attach.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 68eea5b..5c38854 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -919,6 +919,15 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
 	err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
 	if (err < 0)
 		return err;
+
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	/*
+	 * Before analyze VID header, call ubi_bakvol_peb_scan to
+	 * find out backup block and build the backup log volume first.
+	 */
+	ubi_bakvol_peb_scan(ubi, vidh, pnum);
+#endif
+
 	switch (err) {
 	case 0:
 		break;
@@ -995,7 +1004,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
 		*vid = vol_id;
 	if (sqnum)
 		*sqnum = be64_to_cpu(vidh->sqnum);
-	if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
+	if ((vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID)
+					&& vol_id != UBI_BACKUP_VOLUME_ID) {
 		int lnum = be32_to_cpu(vidh->lnum);
 
 		/* Unsupported internal volume */
@@ -1408,6 +1418,12 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 	if (!ai)
 		return -ENOMEM;
 
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	err = ubi_bakvol_module_init(ubi);
+	if (err)
+		goto out_ai;
+#endif
+
 #ifdef CONFIG_MTD_UBI_FASTMAP
 	/* On small flash devices we disable fastmap in any case. */
 	if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) {
@@ -1449,6 +1465,12 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
 	if (err)
 		goto out_ai;
 
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	err = ubi_bakvol_module_init_tail(ubi, ai);
+	if (err)
+		goto out_ai;
+#endif
+
 	err = ubi_wl_init(ubi, ai);
 	if (err)
 		goto out_vtbl;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 14/17] drivers:mtd:ubi:add backup operation in ubi_io_write
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (12 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 13/17] drivers:mtd:ubi:add bakvol init while attach ubi Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  3:22   ` kbuild test robot
  2016-02-02  2:30   ` Bean Huo
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

This patch is to add backup lower page data codes in ubi_io_write.
If programming lower page, bakvol module will duplicate this lower page
data, then program to two different plane pages by multiple plane page program.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/io.c | 73 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 5bbd1f0..6905929 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -222,6 +222,7 @@ retry:
  * @pnum: physical eraseblock number to write to
  * @offset: offset within the physical eraseblock where to write
  * @len: how many bytes to write
+ * @safeguard: if these data has to be duplicated to backup
  *
  * This function writes @len bytes of data from buffer @buf to offset @offset
  * of physical eraseblock @pnum. If all the data were successfully written,
@@ -233,11 +234,12 @@ retry:
  * to the flash media, but may be some garbage.
  */
 int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
-		 int len)
+		 int len, int safeguard)
 {
 	int err;
-	size_t written;
+	size_t retlen;
 	loff_t addr;
+	int skip;
 
 	dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset);
 
@@ -281,14 +283,61 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
 	}
 
 	addr = (loff_t)pnum * ubi->peb_size + offset;
-	err = mtd_write(ubi->mtd, addr, len, &written, buf);
-	if (err) {
-		ubi_err(ubi, "error %d while writing %d bytes to PEB %d:%d, written %zd bytes",
-			err, len, pnum, offset, written);
-		dump_stack();
-		ubi_dump_flash(ubi, pnum, offset, len);
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	skip = 0;
+	if (((offset == 0) && (len == ubi->peb_size)) ||
+		!safeguard)
+		skip = 1;
+
+	if (ubi_check_bakvol_module(ubi) && (!skip)) {
+		loff_t addr_temp;
+		unsigned char *buf_temp = (unsigned char *)buf;
+		int len_temp;
+		int writelen = 0;
+
+		addr_temp = addr;
+
+		for (len_temp = len; len_temp > 0; len_temp -= ubi->min_io_size,
+			addr_temp += ubi->min_io_size,
+			buf_temp += ubi->min_io_size) {
+			/* Split data according to min_io_size */
+
+			if (len_temp/ubi->min_io_size)
+				writelen = ubi->min_io_size;
+			else
+				writelen %= ubi->min_io_size;
+
+			if (is_backup_need(ubi, addr_temp)) {
+				err = ubi_duplicate_data_to_bakvol(ubi,
+					addr_temp, writelen, &retlen, buf_temp);
+				} else
+				err = mtd_write(ubi->mtd, addr_temp, writelen,
+						&retlen, buf_temp);
+
+			if (err) {
+				ubi_err(ubi, "Writing %d byptes to PEB %d:%d",
+					writelen, pnum, offset);
+				ubi_err(ubi, "Error %d", err);
+				ubi_err(ubi, "Written %d bytes", retlen);
+				dump_stack();
+				ubi_dump_flash(ubi, pnum, offset, writelen);
+				} else
+				ubi_assert(retlen == writelen);
+		}
 	} else
-		ubi_assert(written == len);
+#endif
+	{
+		err = mtd_write(ubi->mtd, addr, len, &retlen, buf);
+		if (err) {
+			ubi_err(ubi, "Writing %d byptes to PEB %d:%d",
+				len, pnum, offset);
+			ubi_err(ubi, "Error %d", err);
+			ubi_err(ubi, "Written %zd bytes", retlen);
+			dump_stack();
+			ubi_dump_flash(ubi, pnum, offset, len);
+		} else
+			ubi_assert(retlen == len);
+	}
 
 	if (!err) {
 		err = self_check_write(ubi, buf, pnum, offset, len);
@@ -438,7 +487,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
 
 		/* Write a pattern and check it */
 		memset(ubi->peb_buf, patterns[i], ubi->peb_size);
-		err = ubi_io_write(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
+		err = ubi_io_write(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size, 0);
 		if (err)
 			goto out;
 
@@ -862,7 +911,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
 	if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE))
 		return -EROFS;
 
-	err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
+	err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize, 0);
 	return err;
 }
 
@@ -1114,7 +1163,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
 
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
 	err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
-			   ubi->vid_hdr_alsize);
+			   ubi->vid_hdr_alsize, 0);
 	return err;
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 15/17] fs:ubifs:enable bakvol module and  recover operation
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
@ 2016-02-02  2:30   ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 02/17] include:mtd:add multi-plane program in mtd_info Bean Huo
                     ` (16 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

Before mounting, bakvol will do recovery operaion according to
master node flag(clearly unmount or not). If corrupted page damaged by
power loss exists, bakvol will reocover it through its backup page data.
bakvol module will be enable after ubifs mount successfully.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 fs/ubifs/super.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..0aaeafa 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1270,6 +1270,11 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->need_recovery = 1;
 	}
 
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	if (c->need_recovery)
+		ubi_corrupted_data_recovery(c->ubi);
+#endif
+
 	if (c->need_recovery && !c->ro_mount) {
 		err = ubifs_recover_inl_heads(c, c->sbuf);
 		if (err)
@@ -1463,6 +1468,8 @@ static int mount_ubifs(struct ubifs_info *c)
 	dbg_gen("max. seq. number:    %llu", c->max_sqnum);
 	dbg_gen("commit number:       %llu", c->cmt_no);
 
+	init_bakvol(c->ubi, 1);
+
 	return 0;
 
 out_infos:
@@ -1774,6 +1781,10 @@ static void ubifs_put_super(struct super_block *sb)
 	 * the mutex is locked.
 	 */
 	mutex_lock(&c->umount_mutex);
+
+	/* Disable ubi MLC power loss backup function */
+	init_bakvol(c->ubi, 0);
+
 	if (!c->ro_mount) {
 		/*
 		 * First of all kill the background thread to make sure it does
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 15/17] fs:ubifs:enable bakvol module and recover operation
@ 2016-02-02  2:30   ` Bean Huo
  0 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

Before mounting, bakvol will do recovery operaion according to
master node flag(clearly unmount or not). If corrupted page damaged by
power loss exists, bakvol will reocover it through its backup page data.
bakvol module will be enable after ubifs mount successfully.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 fs/ubifs/super.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..0aaeafa 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1270,6 +1270,11 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->need_recovery = 1;
 	}
 
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	if (c->need_recovery)
+		ubi_corrupted_data_recovery(c->ubi);
+#endif
+
 	if (c->need_recovery && !c->ro_mount) {
 		err = ubifs_recover_inl_heads(c, c->sbuf);
 		if (err)
@@ -1463,6 +1468,8 @@ static int mount_ubifs(struct ubifs_info *c)
 	dbg_gen("max. seq. number:    %llu", c->max_sqnum);
 	dbg_gen("commit number:       %llu", c->cmt_no);
 
+	init_bakvol(c->ubi, 1);
+
 	return 0;
 
 out_infos:
@@ -1774,6 +1781,10 @@ static void ubifs_put_super(struct super_block *sb)
 	 * the mutex is locked.
 	 */
 	mutex_lock(&c->umount_mutex);
+
+	/* Disable ubi MLC power loss backup function */
+	init_bakvol(c->ubi, 0);
+
 	if (!c->ro_mount) {
 		/*
 		 * First of all kill the background thread to make sure it does
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 16/17] driver:mtd:ubi:add new bakvol module in ubi layer
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (14 preceding siblings ...)
  2016-02-02  2:30   ` Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
  2016-02-02 23:06 ` [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Richard Weinberger
  17 siblings, 0 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

Bakvol(bakckup volume) module is for MLC NAND paired page power loss issue.
This patch file is to add new file in mtd/ubi folder.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/bakvol.c | 1296 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1296 insertions(+)
 create mode 100644 drivers/mtd/ubi/bakvol.c

diff --git a/drivers/mtd/ubi/bakvol.c b/drivers/mtd/ubi/bakvol.c
new file mode 100644
index 0000000..a6b1a31
--- /dev/null
+++ b/drivers/mtd/ubi/bakvol.c
@@ -0,0 +1,1296 @@
+/* This version ported to the Linux-UBI system by Micron
+ *
+ * Based on: Micorn APPARATUSES AND METHODS FOR MEMORY MANAGEMENT
+ *
+ */
+
+/*===========================================
+  A UBI solution for MLC NAND powerloss
+
+  This driver implements backup lower page to an UBI internal bakvol volume.
+
+  The contents of this file are subject to the Mozilla Public
+  License Version 1.1 (the "License"); You may obtain a copy of
+  the License at http://www.mozilla.org/MPL/.But you can use this
+  file, no matter in compliance with the License or not.
+
+  The initial developer of the original code is Beanhuo
+  <beanhuo@micorn.com>. Portions created by Micorn.
+
+  Alternatively, the contents of this file may be used under the
+  terms of the GNU General Public License version 2 (the "GPL"), in
+  which case the provisions of the GPL are applicable instead of the
+  above.  If you wish to allow the use of your version of this file
+  only under the terms of the GPL and not to allow others to use
+  your version of this file under the MPL, indicate your decision
+  by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL.  If you do not delete
+  the provisions above, a recipient may use your version of this
+  file under either the MPL or the GPL.
+===========================================*/
+#include <asm/div64.h>
+
+#include <linux/crc32.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+
+#include "ubi.h"
+
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+
+/* Global point for dual plane programming operation */
+struct mtd_oob_ops *oob_ops_bak, *oob_ops_src;
+struct mtd_oob_ops *oob_ops; /* Global read/write ops point */
+
+int Recovery_done; /* 1: bakvol recovery already done. 0: need to do recovery */
+
+/* Temporary variables used during scanning PEB */
+struct ubi_ec_hdr *ech;
+struct ubi_vid_hdr *vidh;
+
+/* Which generation of Micron NAND device will be used */
+#define MICRON_NAND_VERSION_L7X_CONFIG 0
+#define MICRON_NAND_VERSION_L8X_CONFIG 1
+
+/**
+ * is_lowerpage - check page belongs to lower or uppoer page.
+ *		For the detail algorithm, please refer to Micron
+ *		product datasheet "Shared Pages".
+ * @page_num: physical page number within PEB
+ *
+ *  if paeg_num is lower page, return 1
+ *  if page_num is upper page, return 0
+ *  if page_num is SLC page, return -1
+ */
+static int is_lowerpage(int page_num)
+{
+	int ret;
+#if MICRON_NAND_VERSION_L8X_CONFIG
+	/* used for Micron L8x series parallel nand */
+	switch (page_num) {
+	case 2:
+	case 3:
+	case 248:
+	case 249:
+	case 252:
+	case 253:
+	case 254:
+	case 255:
+		ret = -1;/* This page belongs to SLC page. */
+		break;
+	default:
+		if (page_num % 4 < 2) {
+			/* If remainder is 2,3 ,this page belongs to lower page,
+			 * else if 0,1, it belongs to upper page */
+			ret = 1; /* Lower page */
+		} else {
+			ret = 0;
+		}
+		break;
+	}
+#elif MICRON_NAND_VERSION_L7X_CONFIG
+	/* Used for Micron L7X series parallel NAND */
+	switch (page_num) {
+	case 0:
+	case 1:
+		ret = 1;
+		break;
+	case 4:
+	case 5:
+	case 254:
+	case 255: /* 4,5,254, 255 is upper page */
+		ret = 0;
+		break;
+	default:
+		if (page_num % 4 > 1)
+			/* 2 ,3 is lower page, 0,1 is upper page */
+			ret = 1; /* Lower page */
+		else
+			ret = 0;
+		break;
+	}
+#endif
+	return ret;
+}
+
+/**
+ * get_next_lowerpage - return next lower page number.
+ * @page: physical page number within PEB
+ *
+ * This function returns corresponding next lower page nubmer,
+ * if exist lower page; return -1, if this page is already last
+ * page or no lower  page after this page.
+ * Note: For the detail algorithm, please refer to Micron product
+ * datasheet "Shared Pages".
+ */
+static int get_next_lowerpage(int page)
+{
+	int ret = -1;
+#if MICRON_NAND_VERSION_L8X_CONFIG
+	if (page == 254)
+		ret = -1;
+	if (page >= 255)
+		return -1;
+	/* Used for L8x  Micron series NAND */
+	if (page % 4 < 2) {
+		if (page % 2 == 0)
+			ret = page + 1;
+		else {
+			if ((page == 1) || (page == 3))
+				ret = page + 1;
+			else
+				ret = page + 3;
+		}
+
+	} else {
+		if (page % 2 == 0)
+			ret = page + 2;
+		else
+			ret = page + 1;
+	}
+
+	/* Skip SLC page */
+	switch (ret) {
+	case 2:
+	case 3:
+		ret = 4;
+		break;
+	case 248:
+	case 249:
+	case 252:
+	case 253:
+	case 254:
+	case 255:
+		ret = -1;
+		break;
+	default:
+		break;
+	}
+#elif MICRON_NAND_VERSION_L7X_CONFIG
+	/* Used for Micron L7X series NAND */
+	switch (page) {
+	case 0:
+	case 1:
+	case 2:
+		ret = page + 1;
+		break;
+	case 4:
+	case 5:
+		ret = page + 2;
+		break;
+	case 254:
+	case 255:   /* 254, 255 is upper page */
+		ret = -1;
+		break;
+	default:
+		if (page % 4 > 1) {
+			if (page % 2 == 0)
+				ret = page + 1;
+			else
+				ret = page + 3;
+		} else {
+			if (page % 2 == 0)
+				ret = page + 2;
+			else
+				ret = page + 1;
+
+		}
+		break;
+	}
+#endif
+	return ret;
+}
+
+/**
+ * get_oppo_plane_seq - return opposite plane number according to PEB number
+ *
+ *
+ */
+static int get_oppo_plane_seq(struct ubi_device *ubi, loff_t addr)
+{
+	int peb;
+
+	peb = (int)(addr >> ubi->mtd->erasesize_shift);
+
+	if (peb % 2)
+		return 0; /* plane 0 */
+	else
+		return 1; /* plane 1 */
+}
+
+/**
+ * check_original_data - check original data whether being corrupted.
+ * @ubi: UBI device description object
+ * @bak_addr: address of backup page
+ *		if source block not erased, user oob data
+ *		should equal to bak_addr.
+ * @src_addr: source page address
+ * @datbuf: point of backup data
+ */
+static int check_original_data(struct ubi_device *ubi, loff_t bak_addr,
+					loff_t src_addr, uint8_t *datbuf)
+{
+	int i;
+	loff_t read_addr;
+	struct bakvol_oob_info *oob_info;
+	void *buf = datbuf;
+	int ret = -1;
+
+	struct mtd_oob_ops *ops = kmalloc(sizeof(struct mtd_oob_ops),
+						GFP_KERNEL);
+
+	if (!ops) {
+		ubi_err(ubi, "[%d]Error,kmalloc error!\n", __LINE__);
+		goto out;
+	}
+
+	ops->datbuf = kmalloc(ubi->min_io_size, GFP_KERNEL);
+	ops->oobbuf = kmalloc(ubi->mtd->oobsize, GFP_KERNEL);
+	if (!ops->datbuf || !ops->oobbuf) {
+		ubi_err(ubi, "[%d]Error,kmalloc error!\n", __LINE__);
+		goto free;
+	}
+
+	ops->mode = MTD_OPS_AUTO_OOB;
+	ops->ooblen = UBI_BAKVOL_OOB_SIZE;
+	ops->len = ubi->min_io_size;
+	ops->ooboffs = 0;
+	ops->retlen = 0;
+	ops->oobretlen = 0;
+
+	dbg_gen("%s:Source page addr = 0x%llx\n", __func__, src_addr);
+
+	ret = ubi->mtd->_read_oob(ubi->mtd, src_addr, ops);
+
+	if (ret < 0) {
+		/*
+		 * Read error, means this page being corrupted,
+		 * need to recover.
+		 */
+		ret = 1;
+		goto free;
+	}
+
+	oob_info = (struct bakvol_oob_info *)ops->oobbuf;
+	read_addr = be64_to_cpu(oob_info->addr);
+	if (read_addr != bak_addr) {
+		/*
+		 * source page oobbuf != bak_addr, means this PEB already
+		 * being erased or re-programmed. what's more, exsit bitflips
+		 * in user oob area, anyway, current backup page data
+		 * already is not corresponding source page data.
+		*/
+		dbg_gen("[%d] backup page address not match.\n", __LINE__);
+		ret = 0;
+		goto free;
+	}
+
+	for (i = 0; i < ubi->min_io_size; i += 4) {
+		if (*(u32 *)ops->datbuf != *(u32 *)buf) {
+			ret = 1;
+			goto free;
+		}
+	}
+	ret = 0;
+	dbg_gen("Original data not being corrupted.\n");
+
+free:
+	kfree(ops->oobbuf);
+	kfree(ops->datbuf);
+	kfree(ops);
+out:
+	return ret;
+
+}
+/**
+ * find_last_programmed_page - find last page being programmed.
+ * @ubi: UBI device description object
+ * @pnum: PEB number
+ * @ret_page: return last programmed page number
+ */
+static int find_last_programmed_page(struct ubi_device *ubi,
+					int pnum, int *ret_page)
+{
+	struct mtd_info *mtd = ubi->mtd;
+	int page, start_page, err;
+
+	oob_ops->mode = MTD_OPS_AUTO_OOB;
+	oob_ops->ooblen = UBI_BAKVOL_OOB_SIZE;
+	oob_ops->len = ubi->min_io_size;
+	oob_ops->ooboffs = 0;
+	oob_ops->retlen = 0;
+	oob_ops->oobretlen = 0;
+
+	page = (mtd->erasesize - 1) >> mtd->writesize_shift;
+	start_page = ubi->leb_start >> mtd->writesize_shift;
+	for (; page >= start_page; page--) {
+		err = ubi->mtd->_read_oob(ubi->mtd,
+				(pnum << mtd->erasesize_shift) |
+				(page << mtd->writesize_shift), oob_ops);
+
+		if (err < 0 && err != -EUCLEAN) {
+			*ret_page = page;
+			return -1;
+		}
+
+		if (!ubi_check_pattern(oob_ops->oobbuf, 0xFF,
+						oob_ops->ooblen)) {
+			*ret_page = page;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/**
+ * get_peb_from_bakvol - get a PEB that already being opened by bakvol.
+ * @ubi: UBI device description object
+ * @plane: indicates this PEB should belong to which plane
+ * @page_num: indicates which page should not be programmed
+ */
+static struct ubi_bkblk_info *get_peb_from_bakvol(struct ubi_device *ubi,
+						char plane, int page_num)
+{
+	struct ubi_bkblk_tbl *backup_info = ubi->bkblk_tbl;
+	struct list_head *head = &backup_info->head;
+	struct ubi_bkblk_info *bbi, *tempbbi = NULL;
+	int page;
+
+	if (list_empty(head)) {
+		dbg_gen("%s:bakvol no already opened PEB.\n", __func__);
+		return NULL;
+	}
+
+	list_for_each_entry(bbi, head, node) {
+		if (bbi->plane == plane) {
+			page = get_next_lowerpage(bbi->pgnum);
+			if (page == -1)
+				continue;
+			if (page == page_num) {
+				/*
+				 * Perfecct match
+				 */
+				tempbbi = bbi;
+				break;
+			} else if (page < page_num) {
+				/*
+				 * Make sure this page not be programmed.
+				 */
+				if (tempbbi == NULL)
+					tempbbi = bbi;
+				else {
+					if (tempbbi->pgnum > bbi->pgnum)
+						/*
+						 * As far as possible choose
+						 * the PEB with smallest page
+						 * number.
+						 */
+						tempbbi = bbi;
+				}
+			}
+		}
+	}
+
+	if (tempbbi)
+		dbg_gen("Get bakvol PEB %d:%d for original lower page %d.\n",
+				tempbbi->peb, tempbbi->pgnum, page_num);
+	else
+		dbg_gen("Cannot get free bakvol PEB for plane %d:page %d.\n",
+					plane, page_num);
+
+	return tempbbi;
+}
+
+static void prepare_bakvol_oob_info(loff_t *addr,
+			struct bakvol_oob_info *bakvol_oob)
+{
+	uint32_t crc;
+
+	ubi_assert(addr != NULL &&  bakvol_oob != NULL);
+
+	bakvol_oob->addr = cpu_to_be64(*(loff_t *)addr);
+	crc = crc32(UBI_CRC32_INIT, bakvol_oob, UBI_BAKVOL_OOB_SIZE_CRC);
+	bakvol_oob->crc = cpu_to_be32(crc);
+}
+
+/**
+ * validate_bakvol_oob_info- validate bakvol oob user info.
+ * @ubi: UBI device description object
+ * @oob_info: bakvol oob info
+ *
+ * This function returns zero if bakvol oob user info is valid,
+ * and return 1 if not.
+ */
+static int validate_bakvol_oob_info(struct ubi_device *ubi,
+			const struct bakvol_oob_info *oob_info)
+{
+	uint32_t crc, read_crc;
+	int ret = 0;
+
+	crc = crc32(UBI_CRC32_INIT, oob_info, UBI_BAKVOL_OOB_SIZE_CRC);
+	read_crc = be32_to_cpu(oob_info->crc);
+	if (read_crc != crc) {
+		ubi_err(ubi, "OOB info CRC error,calculate 0x%x, read 0x%0x",
+							crc, read_crc);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static struct
+ubi_bkblk_info *find_min_free_space_peb(struct ubi_bkblk_tbl *backup_info)
+{
+	struct list_head *head = &backup_info->head;
+	struct ubi_bkblk_info *bbi, *retbbi;
+
+	retbbi = list_first_entry(head, struct ubi_bkblk_info, node);
+
+	list_for_each_entry(bbi, head, node) {
+		if (bbi->pgnum > retbbi->pgnum)
+			retbbi = bbi;
+	}
+
+	return retbbi;
+}
+
+static struct
+ubi_bkblk_info *allo_new_block_for_bakvol(struct ubi_device *ubi, u8 plane)
+{
+
+	struct ubi_vid_hdr *vid_hdr;
+	struct ubi_volume *vol;
+	struct ubi_bkblk_tbl *backup_info = ubi->bkblk_tbl;
+	struct ubi_bkblk_info *bbin, *newbbin;
+	int bc_plane0, bc_plane1;
+	int pnum;
+	int err;
+	int tries = 1;
+
+	vol = ubi->volumes[vol_id2idx(ubi, UBI_BACKUP_VOLUME_ID)];
+
+	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
+	if (!vid_hdr)
+		return NULL;
+
+	newbbin = kmalloc(sizeof(*newbbin), GFP_ATOMIC);
+	if (!newbbin) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	vid_hdr->vol_type = UBI_VID_DYNAMIC;
+	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+	vid_hdr->vol_id = cpu_to_be32(UBI_BACKUP_VOLUME_ID);
+	vid_hdr->compat = UBI_BACKUP_VOLUME_COMPAT;
+	vid_hdr->data_pad = cpu_to_be32(0);
+	vid_hdr->data_size = vid_hdr->used_ebs = vid_hdr->data_pad;
+
+retry:
+	pnum = ubi_wl_get_plane_peb(ubi, plane);
+
+	if (pnum < 0) {
+		err = -ENOMEM;
+		goto free_mem;
+	}
+
+	if (pnum%2 != plane) {
+		err = pnum;
+		goto free_mem;
+	}
+
+	bc_plane0 = backup_info->bcount_of_plane[0];
+	bc_plane1 = backup_info->bcount_of_plane[1];
+
+	if (bc_plane0 + bc_plane1 >= vol->reserved_pebs) {
+		/**
+		 * we make sure bakvol opened PEBs cannot overflow
+		 * bakvol reserved PEB.
+		 */
+		dbg_gen("bakvol opened PEB over reserved PEB.\n");
+		dbg_gen("Will put PEB with minimum free space.\n");
+		bbin = find_min_free_space_peb(backup_info);
+
+		if (vol->eba_tbl[bbin->leb] >= 0) {
+			dbg_gen("bakvol put PEB %d.\n", bbin->peb);
+			err = ubi_wl_put_peb(ubi, vol->vol_id, bbin->leb,
+							bbin->peb, 0);
+			if (err)
+				goto free_mem;
+		}
+
+		vol->eba_tbl[bbin->leb] = UBI_LEB_UNMAPPED;
+		backup_info->bcount_of_plane[bbin->plane]--;
+		newbbin->leb = bbin->leb;
+
+		list_del(&bbin->node);
+
+	} else {
+		int i = 0;
+
+		for (i = 0; i < vol->reserved_pebs; i++)
+			if (vol->eba_tbl[i] == UBI_LEB_UNMAPPED) {
+				newbbin->leb = i;
+				break;
+			}
+	}
+
+	vid_hdr->lnum = cpu_to_be32(newbbin->leb);
+	if ((newbbin->leb > vol->reserved_pebs) || (newbbin->leb < 0)) {
+		ubi_err(ubi, "BUG: logic block number [%d] error.\n", newbbin->leb);
+		panic("BUG!");
+	}
+
+	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
+	if (err) {
+		ubi_err(ubi, "Failed to write VID header to PEB %d.\n", pnum);
+		goto write_error;
+	}
+
+	vol->eba_tbl[newbbin->leb] = pnum;
+
+	newbbin->peb = pnum;
+	newbbin->plane = plane;
+	newbbin->pgnum = get_next_lowerpage(1); /* Skip page0 and page1 */
+
+	/* Update bakvol variable */
+	backup_info->bcount_of_plane[plane]++;
+	list_add(&newbbin->node, &backup_info->head);
+
+out:
+	ubi_free_vid_hdr(ubi, vid_hdr);
+	return newbbin;
+
+write_error:
+	/*
+	 * Bad luck? This physical eraseblock is bad too?  Let's try to
+	 * get another one.
+	 */
+	ubi_err(ubi, "Failed to write to PEB %d", pnum);
+	ubi_wl_put_peb(ubi, vol->vol_id, newbbin->leb, newbbin->peb, 1);
+	if (++tries > UBI_IO_RETRIES)
+		goto free_mem;
+
+	ubi_err(ubi, "Try again");
+	goto retry;
+
+free_mem:
+	ubi_free_vid_hdr(ubi, vid_hdr);
+	kfree(newbbin);
+	ubi_err(ubi, "%s:%d %d times failed to alloc a new block!",
+			__func__, __LINE__, tries);
+	return NULL;
+}
+
+/**
+ * is_backup_need -check if this page date need to be backup.
+ * @ubi: UBI device description object
+ * @addr: page address
+ *
+ * return 0, this page data shouldn't  backup
+ * return 1, this page data should  backup
+ */
+int is_backup_need(struct ubi_device *ubi, loff_t addr)
+{
+	int page_num, ret;
+
+	page_num = (addr & ubi->mtd->erasesize_mask) >>
+						ubi->mtd->writesize_shift;
+	if (page_num == 0 || page_num == 1)
+		/* Currently,we don't backup EC head and VID head */
+		return 0;
+
+	ret = is_lowerpage(page_num);
+	if (ret != 1) {
+		dbg_gen("Page %d is %s page.\n", page_num,
+				(ret == -1 ? "SLC" : "upper"));
+		ret = 0;
+	} else
+		dbg_gen("Page %d is lower page.\n", page_num);
+
+	return ret;
+}
+
+/**
+ * ubi_check_bakvol_module - check if bakvol has been buildup
+ * @ubi: UBI device description object
+ *
+ * returns 1 in case of  backup volume have been built,
+ * 0 in case of don't find
+ */
+int ubi_check_bakvol_module(struct ubi_device *ubi)
+{
+	return (ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_ENABLE);
+}
+
+/**
+ * ubi_duplicate_data_to_bakvol - dual plane program data into bakvol area
+ *			and main area respectively.
+ * @ubi: UBI device description object
+ * @addr: address will be programmed
+ * @len: date length
+ * @retlen: already programmed data length
+ * @buf: data buffer, points to data that should be programmed
+ */
+int ubi_duplicate_data_to_bakvol(struct ubi_device *ubi, loff_t addr,
+				size_t len, size_t *retlen, const void *buf)
+{
+	struct ubi_bkblk_tbl *backup_info = ubi->bkblk_tbl;
+	struct mtd_info *mtd = ubi->mtd;
+	int err = 0, nobak = 0;
+	int pnum;
+	u8 oppe_plane;
+	loff_t lpage_addr; /* Lower page byte address */
+	struct ubi_bkblk_info *pbk;
+	int page_num;
+	struct bakvol_oob_info *oob_bak = NULL, *oob_src = NULL;
+
+	if (len > ubi->min_io_size) {
+		ubi_err(ubi, "%d: Write data len overflow [%d]\n",
+							__LINE__, len);
+		return -EROFS;
+	}
+
+	if (!buf) {
+		ubi_err(ubi, "%d: Write buf is NULL!\n", __LINE__);
+		return -EROFS;
+
+	}
+	oppe_plane = get_oppo_plane_seq(ubi, addr);
+
+	page_num = (int)(addr & ubi->mtd->erasesize_mask) >>
+						ubi->mtd->writesize_shift;
+	pnum = (int)(addr >> ubi->mtd->erasesize_shift);
+
+	oob_bak = kzalloc(UBI_BAKVOL_OOB_SIZE, GFP_KERNEL);
+	if (!oob_bak) {
+		err = -ENOMEM;
+		ubi_err(ubi, "%s:%d: kzalloc error.\n",
+						__func__, __LINE__);
+		goto free;
+	}
+
+	oob_src = kzalloc(UBI_BAKVOL_OOB_SIZE, GFP_KERNEL);
+	if (!oob_src) {
+		err = -ENOMEM;
+		ubi_err(ubi, "%s:%d: kzalloc error.\n",
+						__func__, __LINE__);
+		goto free;
+	}
+
+	if (backup_info->bcount_of_plane[oppe_plane] == 0)
+		pbk = NULL;
+	else
+		pbk = get_peb_from_bakvol(ubi, oppe_plane, page_num);
+
+	if (pbk == NULL) {
+		dbg_gen("Allocate new PEB for Bakvol.\n");
+		pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
+		if (!pbk) {
+			ubi_err(ubi, "Allocate new PEB failed.\n");
+			nobak = 1;
+			goto Only_source;
+		}
+	}
+
+	/*
+	 * Here original page address stores in user oob area of bakvol page,
+	 * and corresponding its backup page address stores in user oob area of
+	 * main data area page.
+	*/
+	lpage_addr = (pbk->peb << mtd->erasesize_shift) |
+				(page_num << mtd->writesize_shift);
+
+	/*
+	 * organize bakvol page ops
+	*/
+	oob_ops_bak->datbuf = (uint8_t *)buf;
+	oob_ops_bak->mode = MTD_OPS_AUTO_OOB;
+	oob_ops_bak->ooblen = UBI_BAKVOL_OOB_SIZE;
+	prepare_bakvol_oob_info(&addr, oob_bak);
+	oob_ops_bak->oobbuf = (uint8_t *)oob_bak; /* Original page addr */
+	oob_ops_bak->len = len;
+	oob_ops_bak->ooboffs = 0;
+	oob_ops_bak->retlen = 0;
+	oob_ops_bak->oobretlen = 0;
+
+Only_source:
+	/*
+	 * Organize main data area page ops
+	*/
+	oob_ops_src->datbuf = (uint8_t *)buf;
+	oob_ops_src->mode = MTD_OPS_AUTO_OOB;
+	oob_ops_src->ooblen = UBI_BAKVOL_OOB_SIZE;
+	prepare_bakvol_oob_info(&lpage_addr, oob_src);
+	oob_ops_src->oobbuf = (uint8_t *)oob_src; /* backup page addr */
+	oob_ops_src->len = len;
+	oob_ops_src->ooboffs = 0;
+	oob_ops_src->retlen = 0;
+	oob_ops_src->oobretlen = 0;
+
+	if (!nobak)
+		err = mtd_write_dual_plane_oob(ubi->mtd, lpage_addr,
+						oob_ops_bak, addr, oob_ops_src);
+
+	if ((err == -EOPNOTSUPP) || (nobak == 1)) {
+		/*
+		 * If dual plane program function not enable, or get
+		 * bakvol peb failed, we only program original data to
+		 * main data area.
+		*/
+		ubi_err(ubi, "Only program source data.\n");
+		err = mtd_write_oob(ubi->mtd, addr, oob_ops_src);
+		goto out;
+	}
+
+	pbk->pgnum = page_num; /* updata bakvol PEB programmed page info */
+
+out:
+	if (err)
+		*retlen = 0;
+	else
+		*retlen = len;
+free:
+	kfree(oob_bak);
+	kfree(oob_src);
+	return err;
+}
+
+
+int ubi_bakvol_module_init(struct ubi_device *ubi)
+{
+	int step;
+
+	if ((ubi->mtd->type != MTD_MLCNANDFLASH) ||
+		(ubi->mtd->oobavail < UBI_BAKVOL_OOB_SIZE)) {
+		ubi_err(ubi, "NAND cann't meet Bakvol module requirement.\n");
+		step = 0;
+		goto out_init;
+	}
+
+	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+	if (!ech) {
+		step = 1;
+		goto out_init;
+	}
+
+	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+	if (!vidh) {
+		step = 2;
+		goto out_ech;
+	}
+
+	ubi->bkblk_tbl = kzalloc(sizeof(struct ubi_bkblk_tbl), GFP_KERNEL);
+	if (!ubi->bkblk_tbl) {
+		step = 3;
+		goto out_vidh;
+	}
+	ubi->bkblk_tbl->bcount_of_plane[0] = 0;
+	ubi->bkblk_tbl->bcount_of_plane[1] = 0;
+	INIT_LIST_HEAD(&ubi->bkblk_tbl->head);
+
+	oob_ops_bak = kzalloc(sizeof(struct mtd_oob_ops), GFP_KERNEL);
+	if (!oob_ops_bak) {
+		step = 4;
+		goto out_backup_info;
+	}
+
+	oob_ops_bak->oobbuf = kzalloc(ubi->mtd->oobsize, GFP_KERNEL);
+	if (!oob_ops_bak->oobbuf) {
+		step = 5;
+		goto out_back_oob_ops;
+	}
+
+	oob_ops_src = kzalloc(sizeof(struct mtd_oob_ops), GFP_KERNEL);
+	if (!oob_ops_src) {
+		step = 6;
+		goto out_obs_src;
+	}
+
+	oob_ops_src->oobbuf = kzalloc(ubi->mtd->oobsize, GFP_KERNEL);
+	if (!oob_ops_src->oobbuf) {
+		step = 7;
+		goto out_oob_ops;
+	}
+
+	oob_ops = kmalloc(sizeof(struct mtd_oob_ops), GFP_KERNEL);
+	if (!oob_ops) {
+		step = 8;
+		goto out0;
+	}
+
+	oob_ops->datbuf = kmalloc(ubi->min_io_size, GFP_KERNEL);
+	if (!oob_ops->datbuf) {
+		step = 9;
+		goto out1;
+	}
+
+	oob_ops->oobbuf = kmalloc(ubi->mtd->oobsize, GFP_KERNEL);
+	if (!oob_ops->oobbuf) {
+		step = 10;
+		goto out2;
+	}
+
+	ubi_free_vid_hdr(ubi, vidh);
+	kfree(ech);
+
+	ubi->bkblk_tbl->bakvol_flag = UBI_BAKVOL_INIT_START;
+	return 0;
+
+out2:
+	kfree(oob_ops->datbuf);
+out1:
+	kfree(oob_ops);
+out0:
+	kfree(oob_ops_src->oobbuf);
+out_oob_ops:
+	kfree(oob_ops_src);
+out_obs_src:
+	kfree(oob_ops_bak->oobbuf);
+out_back_oob_ops:
+	kfree(oob_ops_bak);
+out_backup_info:
+	kfree(ubi->bkblk_tbl);
+out_vidh:
+	ubi_free_vid_hdr(ubi, vidh);
+out_ech:
+	kfree(ech);
+out_init:
+	ubi_err(ubi, "bakvol module init error,init step [%d].\n", step);
+	ubi->bkblk_tbl->bakvol_flag = UBI_BAKVOL_REJECT;
+	return -1;
+}
+
+/**
+ * ubi_bakvol_peb_scan - check VID header,see if this PEB
+ *				belongs to bakvol
+ *
+ * This function returns 1 if this PEB not belongs to bakvol
+ * return -1 in case of allocate resource error
+ * return 0  if scan complete, and it belongs to bakvol
+ */
+int ubi_bakvol_peb_scan(struct ubi_device *ubi, struct ubi_vid_hdr *vidh,
+								int pnum)
+{
+	int page;
+	int vol_id;
+	struct ubi_bkblk_info *bbi;
+	int lnum;
+	int ret;
+
+	page = 0;
+
+	vol_id = be32_to_cpu(vidh->vol_id);
+	if (vol_id == UBI_BACKUP_VOLUME_ID) {
+		/* Found bakvol PEB */
+		lnum = be32_to_cpu(vidh->lnum);
+		dbg_gen("%s:Found backup PEB,pnum is [%d],lnum is[%d].\n",
+							__func__, pnum, lnum);
+
+		/* Unsupported internal volume */
+		if (vidh->compat != UBI_COMPAT_REJECT) {
+			ubi_err(ubi, "Backup volume compat != UBI_COMPAT_REJECT\n");
+			return -1;
+		}
+	} else {
+		return 1;
+	}
+
+	ret = find_last_programmed_page(ubi, pnum, &page);
+	dbg_gen("bakvol PEB %d last programmed page [%d]\n", pnum, page);
+
+	if (ret == 1) {
+		bbi = kmalloc(sizeof(*bbi), GFP_ATOMIC);
+		if (!bbi)
+			goto out;
+
+		bbi->peb = pnum;
+		bbi->leb = lnum;
+		bbi->pgnum = page;
+		bbi->plane = pnum % 2;
+		bbi->plane ? (ubi->bkblk_tbl->bcount_of_plane[1]++) :
+					(ubi->bkblk_tbl->bcount_of_plane[0]++);
+		list_add(&bbi->node, &ubi->bkblk_tbl->head);
+	} else if (ret == 0) {
+		/* This backup PEB has not been programmed. */
+		bbi = kmalloc(sizeof(*bbi), GFP_ATOMIC);
+		if (!bbi)
+			goto out;
+		bbi->peb = pnum;
+		bbi->leb = lnum;
+		bbi->pgnum = get_next_lowerpage(1);
+		bbi->plane = pnum % 2;
+		bbi->plane ? (ubi->bkblk_tbl->bcount_of_plane[1]++) :
+					(ubi->bkblk_tbl->bcount_of_plane[0]++);
+		list_add(&bbi->node, &ubi->bkblk_tbl->head);
+	} else {
+		/* Backup block is corrupted,maybe power cut happened during
+		 * programming lower page. so this backup block with corrupted
+		 * page can be removed from bakvol volume.
+		 */
+		dbg_gen("PEB %d will be removed from backup volume later.\n",
+									pnum);
+
+		bbi = kmalloc(sizeof(*bbi), GFP_ATOMIC);
+		if (!bbi)
+			goto out;
+		bbi->peb = pnum;
+		bbi->leb = lnum;
+		bbi->pgnum = page;
+		bbi->plane = pnum % 2;
+		bbi->plane ? (ubi->bkblk_tbl->bcount_of_plane[1]++) :
+				(ubi->bkblk_tbl->bcount_of_plane[0]++);
+		list_add(&bbi->node, &ubi->bkblk_tbl->head);
+	}
+
+	return 0;
+out:
+	return -1;
+
+}
+
+/**
+ * ubi_bakvol_module_init_tail - init backup volume.
+ * @ubi: UBI device description object
+ * @si: scanning information
+ *
+ * This function init the backup volume
+ * Returns zero in case of success and a negative
+ * error code in case of failure
+ */
+int ubi_bakvol_module_init_tail(struct ubi_device *ubi,
+					struct ubi_attach_info *si)
+{
+	int reserved_pebs = 0;
+	struct ubi_volume *vol;
+	struct ubi_bkblk_info *bbi;
+
+	if (ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_REJECT)
+		return 0;
+
+	if (!(ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_INIT_DONE)) {
+
+		/* And add the layout volume */
+		vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);
+		if (!vol)
+			return -ENOMEM;
+
+		vol->reserved_pebs = UBI_BACKUP_VOLUME_EBS;
+		vol->alignment = 1;
+		vol->vol_type = UBI_DYNAMIC_VOLUME;
+		vol->name_len = sizeof(UBI_BACKUP_VOLUME_NAME) - 1;
+		vol->data_pad = 0;
+		memcpy(vol->name, UBI_BACKUP_VOLUME_NAME, vol->name_len + 1);
+
+		vol->usable_leb_size = ubi->leb_size;
+		vol->used_ebs = vol->reserved_pebs;
+		vol->last_eb_bytes = vol->reserved_pebs;
+		vol->used_bytes =
+		    (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad);
+		vol->vol_id = UBI_BACKUP_VOLUME_ID;
+		vol->ref_count = UBI_BACKUP_VOLUME_EBS;
+		ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol;
+		reserved_pebs += vol->reserved_pebs;
+		ubi->vol_count += 1;
+		vol->ubi = ubi;
+		if (reserved_pebs > ubi->avail_pebs) {
+			ubi_err(ubi, "No enough PEBs, required %d, available %d",
+				reserved_pebs, ubi->avail_pebs);
+			return -1;
+		}
+		ubi->rsvd_pebs += reserved_pebs;
+		ubi->avail_pebs -= reserved_pebs;
+
+		ubi->bkblk_tbl->bakvol_flag = UBI_BAKVOL_INIT_DONE;
+
+		ubi_msg(ubi, "bakvol module opened PEB list:");
+		list_for_each_entry(bbi, &(ubi->bkblk_tbl->head), node) {
+			ubi_msg(ubi, "peb %d,pgnum %d,plane %d,;leb %d.",
+				bbi->peb, bbi->pgnum, bbi->plane, bbi->leb);
+		}
+	}
+	return 0;
+}
+
+int ubi_corrupted_data_recovery(struct ubi_volume_desc *desc)
+{
+	u32 base_offset, buff_offset, pnum, offset, page;
+	u32 correct, uncorrect_l, uncorrect_h;
+	int ret, err;
+	struct ubi_device *ubi = desc->vol->ubi;
+	struct mtd_info *mtd = ubi->mtd;
+	struct ubi_bkblk_info *bbi;
+	unsigned char *buf = ubi->peb_buf;
+	struct ubi_volume_desc volume_desc;
+	int i, move;
+	loff_t bakpage_addr;
+	struct bakvol_oob_info *oob_info;
+	off_t src_addr;
+
+	move = 0;
+	correct = 0;
+	uncorrect_h = 0;
+	uncorrect_l = 0;
+
+	if ((ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_RECOVERY) ||
+		!(ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_INIT_DONE))
+		return 0;
+
+	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+	if (!vidh)
+		return -1;
+
+	oob_ops->mode = MTD_OPS_AUTO_OOB;
+	oob_ops->ooblen = UBI_BAKVOL_OOB_SIZE;
+	oob_ops->len = ubi->min_io_size;
+
+	list_for_each_entry(bbi, &(ubi->bkblk_tbl->head), node) {
+		dbg_gen("Processing bakvol PEB %d,pgnum %d,plane %d.\n",
+			bbi->peb, bbi->pgnum, bbi->plane);
+		i = get_next_lowerpage(1);
+
+		for ( ; (i <= bbi->pgnum) && (i != -1);
+				i = get_next_lowerpage(i)) {
+			/*
+			 * Read backup data from bakvol PEB with OOB.
+			*/
+			oob_ops->ooboffs = 0;
+			oob_ops->retlen = 0;
+			oob_ops->oobretlen = 0;
+
+			err = ubi->mtd->_read_oob(ubi->mtd,
+					(bbi->peb << mtd->erasesize_shift) |
+					(i << mtd->writesize_shift), oob_ops);
+
+			if (err < 0 && err != -EUCLEAN) {
+				dbg_gen("Read bakvol PEB %d:%d error %d.\n",
+						bbi->peb, i, err);
+				move = 1;
+				continue;
+			}
+
+			if (ubi_check_pattern(oob_ops->oobbuf, 0xFF,
+						oob_ops->ooblen)) {
+				dbg_gen("Bakvol PEB %d ever skip lower page %d.\n",
+						bbi->peb, i);
+				continue;
+			}
+
+			oob_info = (struct bakvol_oob_info *)oob_ops->oobbuf;
+
+			if (validate_bakvol_oob_info(ubi, oob_info)) {
+				dbg_gen("Bakvol PEB %d page %d user oob area exist bitflips.\n",
+						bbi->peb, i);
+				continue;
+			}
+
+		src_addr = be64_to_cpu(oob_info->addr);
+
+		/*
+		 * Calculate backup page address, used for check if source block
+		 * already being erased or re-mapped.
+		*/
+		bakpage_addr = (bbi->peb << mtd->erasesize_shift) |
+					(i << mtd->writesize_shift);
+
+		ret = check_original_data(ubi, bakpage_addr,
+						src_addr, oob_ops->datbuf);
+		  if (ret == 1) {
+			/* The original data isn't correct anymore,
+			 * already being damaged, and oobbuf store original page
+			 * address.
+			 */
+			pnum = src_addr >> mtd->erasesize_shift;
+			offset = src_addr & mtd->erasesize_mask;
+			buff_offset = 0;
+
+			/**
+			 * Recover operation
+			 */
+
+			for (base_offset = ubi->leb_start;
+				base_offset < ubi->peb_size;
+				base_offset += mtd->writesize) {
+
+				ret = ubi_io_read(ubi, buf + buff_offset, pnum,
+						base_offset, mtd->writesize);
+
+			if (ret == -EBADMSG || ret == -EIO) {
+				if (base_offset == offset) {
+				    dbg_gen("Bakvol recover offset 0x%x.....\n",
+						base_offset);
+				    memcpy(buf + buff_offset, oob_ops->datbuf,
+							mtd->writesize);
+				    correct++;
+				} else {
+				    page = base_offset >> mtd->writesize_shift;
+					if (is_lowerpage(page)) {
+						/* More low-page also
+						 * be corrupted */
+						uncorrect_l++;
+					ubi_err(ubi, "PEB %d unrecovery lower page %d\n",
+								pnum, page);
+					uncorrect_l++;
+					} else {
+					/**
+					 * Unbackup upper page also
+					 * be corruptted */
+					ubi_err(ubi, "PEB %d unrecovery upper page %d.\n",
+								pnum, page);
+					uncorrect_h++;
+					}
+				}
+			}
+
+			ret = ubi_check_pattern(buf + buff_offset, 0xFF,
+							mtd->writesize);
+			if (ret)
+				/* This page is empty, so the last of pages
+				 * also are empty, no need to read.*/
+				break;
+
+			buff_offset += mtd->writesize;
+			}
+
+		if ((correct == 0) || (uncorrect_h > 1) || (uncorrect_l > 0)) {
+			/* Could not recover. We only accept two corrupted
+			 * pages, they are paired-page. If there are two
+			 * corrupted lower pages within one PEB, also give
+			 * up recovery.
+			 */
+			dbg_gen("Can not be recoverred.\n");
+			uncorrect_l = 0;
+			uncorrect_h = 0;
+			continue;
+			}
+
+		ret = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
+
+		volume_desc.vol = ubi->volumes[be32_to_cpu(vidh->vol_id)];
+		volume_desc.mode = UBI_READWRITE;
+		ret = ubi_leb_change(&volume_desc, be32_to_cpu(vidh->lnum),
+							buf, buff_offset);
+		correct = 0;
+		uncorrect_h = 0;
+
+		if (ret) {
+			ubi_err(ubi, "Changing %d bytes in LEB %d failed",
+						buff_offset, vidh->lnum);
+			ubi_err(ubi, "Ret error:%d.", ret);
+			dump_stack();
+		} else
+			dbg_gen(".....Done\n");
+
+	  }
+
+	}
+
+		if (move == 1) {
+		    bbi->pgnum = (ubi->mtd->erasesize - 1) >>
+					ubi->mtd->writesize_shift;
+		    move = 0;
+		}
+	}
+	ubi->bkblk_tbl->bakvol_flag |= UBI_BAKVOL_RECOVERY;
+	ubi_free_vid_hdr(ubi, vidh);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ubi_corrupted_data_recovery);
+
+void clear_bakvol(struct ubi_device *ubi)
+{
+	kfree(oob_ops->datbuf);
+	kfree(oob_ops);
+	kfree(oob_ops_src->oobbuf);
+	kfree(oob_ops_src);
+	kfree(oob_ops_bak->oobbuf);
+	kfree(oob_ops_bak);
+	kfree(ubi->bkblk_tbl);
+	ubi->bkblk_tbl->bakvol_flag = UBI_BAKVOL_INIT_START;
+}
+
+void init_bakvol(struct ubi_volume_desc *desc, uint8_t choice)
+{
+	struct ubi_volume *vol = desc->vol;
+	struct ubi_device *ubi = vol->ubi;
+
+	if (choice) {
+		if (ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_INIT_DONE ||
+			ubi->bkblk_tbl->bakvol_flag & UBI_BAKVOL_DISABLE) {
+			dbg_gen("[%s][%d] Enable bakvol module successfully!\n",
+						__func__, __LINE__);
+			ubi->bkblk_tbl->bakvol_flag &= ~UBI_BAKVOL_DISABLE;
+			ubi->bkblk_tbl->bakvol_flag |= UBI_BAKVOL_ENABLE;
+
+		} else
+			dbg_gen("[%s][%d] Enable bakvol module failed!\n",
+					__func__, __LINE__);
+
+	} else {
+		ubi->bkblk_tbl->bakvol_flag &= ~UBI_BAKVOL_ENABLE;
+		ubi->bkblk_tbl->bakvol_flag |= UBI_BAKVOL_DISABLE;
+		dbg_gen("[%s][%d] Disable bakvol module!\n",
+						__func__, __LINE__);
+	}
+}
+EXPORT_SYMBOL_GPL(init_bakvol);
+#else
+int is_backup_need(struct ubi_device *ubi, loff_t addr)
+{
+	return 0;
+}
+
+int ubi_check_bakvol_module(struct ubi_device *ubi)
+{
+
+	return 0;
+}
+
+int ubi_duplicate_data_to_bakvol(struct ubi_device *ubi, loff_t addr,
+				size_t len, size_t *retlen, const void *buf)
+{
+	return 0;
+}
+int ubi_bakvol_module_init(struct ubi_device *ubi)
+{
+	return 0;
+
+}
+
+int ubi_bakvol_peb_scan(struct ubi_device *ubi, struct ubi_vid_hdr *vidh,
+								int pnum)
+{
+	return 0;
+}
+
+int ubi_bakvol_module_init_tail(struct ubi_device *ubi,
+					struct ubi_attach_info *si)
+{
+	return 0;
+}
+
+int ubi_corrupted_data_recovery(struct ubi_volume_desc *desc)
+{
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(ubi_corrupted_data_recovery);
+
+
+void clear_bakvol(struct ubi_device *ubi)
+{
+
+}
+
+void init_bakvol(struct ubi_volume_desc *desc, uint8_t choice)
+{
+
+}
+EXPORT_SYMBOL_GPL(init_bakvol);
+#endif
+
+MODULE_LICENSE("Dual MPL/GPL");
+MODULE_AUTHOR("Bean Huo <beanhuo@micron.com>");
+MODULE_DESCRIPTION("Support code for MLC NAND pair page powerloss protection");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (15 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 16/17] driver:mtd:ubi:add new bakvol module in ubi layer Bean Huo
@ 2016-02-02  2:30 ` Bean Huo
  2016-02-02  3:22   ` kbuild test robot
                     ` (2 more replies)
  2016-02-02 23:06 ` [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Richard Weinberger
  17 siblings, 3 replies; 33+ messages in thread
From: Bean Huo @ 2016-02-02  2:30 UTC (permalink / raw)
  To: richard, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

From: Bean Huo <beanhuo@micron.com>

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/ubi/Kconfig  | 15 +++++++++++++++
 drivers/mtd/ubi/Makefile |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f0855ce..d9f01fa 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -77,6 +77,21 @@ config MTD_UBI_FASTMAP
 
 	   If in doubt, say "N".
 
+config MTD_UBI_MLC_NAND_BAKVOL
+	bool "UBI solution for NAND pair page (Experimental feature)"
+	default n
+	help
+	   This used for MLC NAND paired page power-cut protection.
+
+	   MLC NAND paired page power loss is a known issue so far.
+	   Namely, MLC NAND pages are coupled in a sense that if you cut
+	   power while writing to a page, you corrupt not only this page,
+	   but also one of the previous pages which is paired with the current
+	   one. More detail information,please refer to follwoing link:
+	   http://www.linux-mtd.infradead.org/doc/ubifs.html
+
+	   If in doubt, say "N".
+
 config MTD_UBI_GLUEBI
 	tristate "MTD devices emulation driver (gluebi)"
 	help
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index 4e3c3d7..6bd78aa 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_MTD_UBI) += ubi.o
 
-ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
+ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o bakvol.o
 ubi-y += misc.o debug.o
 ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o
 ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer
  2016-02-02  2:30 ` [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer Bean Huo
@ 2016-02-02  3:00   ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:00 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 1521 bytes --]

Hi Bean,

[auto build test ERROR on v4.5-rc2]
[also build test ERROR on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x012-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   drivers/mtd/mtdpart.c: In function 'part_write_dual_plane_oob':
>> drivers/mtd/mtdpart.c:213:26: error: implicit declaration of function 'PART' [-Werror=implicit-function-declaration]
     struct mtd_part *part = PART(mtd);
                             ^
>> drivers/mtd/mtdpart.c:213:26: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
   cc1: some warnings being treated as errors

vim +/PART +213 drivers/mtd/mtdpart.c

   207	}
   208	
   209	static int part_write_dual_plane_oob(struct mtd_info *mtd, loff_t to_plane0,
   210				    struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
   211				    struct mtd_oob_ops *ops_plane1)
   212	{
 > 213		struct mtd_part *part = PART(mtd);
   214	
   215		if ((to_plane0 >= mtd->size) || ((to_plane1 >= mtd->size)))
   216			return -EINVAL;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 20303 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function
  2016-02-02  2:30 ` [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function Bean Huo
@ 2016-02-02  3:04   ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:04 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 2106 bytes --]

Hi Bean,

[auto build test ERROR on v4.5-rc2]
[also build test ERROR on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x012-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/mtd/nand/nand_base.c: In function 'nand_write_plane_page':
>> drivers/mtd/nand/nand_base.c:2463:12: error: too few arguments to function 'chip->ecc.write_page_raw'
      status = chip->ecc.write_page_raw(mtd, chip, buf,
               ^
>> drivers/mtd/nand/nand_base.c:2466:12: error: too few arguments to function 'chip->ecc.write_subpage'
      status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
               ^
>> drivers/mtd/nand/nand_base.c:2469:12: error: too few arguments to function 'chip->ecc.write_page'
      status = chip->ecc.write_page(mtd, chip, buf, oob_required);
               ^
   drivers/mtd/nand/nand_base.c: At top level:
   drivers/mtd/nand/nand_base.c:3228:12: warning: 'nand_dual_plane_write_oob' defined but not used [-Wunused-function]
    static int nand_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
               ^

vim +2463 drivers/mtd/nand/nand_base.c

  2457		else
  2458			subpage = 0;
  2459	
  2460		chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
  2461	
  2462		if (unlikely(raw))
> 2463			status = chip->ecc.write_page_raw(mtd, chip, buf,
  2464								oob_required);
  2465		else if (subpage)
> 2466			status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
  2467								buf, oob_required);
  2468		else
> 2469			status = chip->ecc.write_page(mtd, chip, buf, oob_required);
  2470	
  2471		if (status < 0)
  2472			return status;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 20303 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer
  2016-02-02  2:30 ` [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer Bean Huo
@ 2016-02-02  3:05   ` kbuild test robot
  2016-02-02  3:08   ` kbuild test robot
  1 sibling, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:05 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 4856 bytes --]

Hi Bean,

[auto build test ERROR on v4.5-rc2]
[also build test ERROR on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x012-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450 HEAD 2078d3920abf1d89be7eaf087100b4482dd532dc builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/mtd/ubi/eba.c: In function 'recover_peb':
>> drivers/mtd/ubi/eba.c:607:8: error: too few arguments to function 'ubi_io_write_data'
     err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
           ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
   drivers/mtd/ubi/eba.c: In function 'ubi_eba_write_leb':
   drivers/mtd/ubi/eba.c:678:9: error: too few arguments to function 'ubi_io_write_data'
      err = ubi_io_write_data(ubi, buf, pnum, offset, len);
            ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
   drivers/mtd/ubi/eba.c:729:9: error: too few arguments to function 'ubi_io_write_data'
      err = ubi_io_write_data(ubi, buf, pnum, offset, len);
            ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
   drivers/mtd/ubi/eba.c: In function 'ubi_eba_write_leb_st':
   drivers/mtd/ubi/eba.c:851:8: error: too few arguments to function 'ubi_io_write_data'
     err = ubi_io_write_data(ubi, buf, pnum, 0, len);
           ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
   drivers/mtd/ubi/eba.c: In function 'ubi_eba_atomic_leb_change':
   drivers/mtd/ubi/eba.c:971:8: error: too few arguments to function 'ubi_io_write_data'
     err = ubi_io_write_data(ubi, buf, pnum, 0, len);
           ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
   drivers/mtd/ubi/eba.c: In function 'ubi_eba_copy_leb':
   drivers/mtd/ubi/eba.c:1197:9: error: too few arguments to function 'ubi_io_write_data'
      err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size);
            ^
   In file included from drivers/mtd/ubi/eba.c:47:0:
   drivers/mtd/ubi/ubi.h:1073:19: note: declared here
    static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf,
                      ^
--
>> drivers/mtd/ubi/io.c:235:5: error: conflicting types for 'ubi_io_write'
    int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
        ^
   In file included from drivers/mtd/ubi/io.c:92:0:
   drivers/mtd/ubi/ubi.h:883:5: note: previous declaration of 'ubi_io_write' was here
    int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
        ^

vim +/ubi_io_write_data +607 drivers/mtd/ubi/eba.c

4df581f3 Artem Bityutskiy    2008-12-04  601  			goto out_unlock;
801c135c Artem B. Bityutskiy 2006-06-27  602  		}
8fb2a514 Richard Weinberger  2014-11-10  603  	}
801c135c Artem B. Bityutskiy 2006-06-27  604  
0ca39d74 Artem Bityutskiy    2012-03-08  605  	memcpy(ubi->peb_buf + offset, buf, len);
801c135c Artem B. Bityutskiy 2006-06-27  606  
0ca39d74 Artem Bityutskiy    2012-03-08 @607  	err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
4df581f3 Artem Bityutskiy    2008-12-04  608  	if (err) {
4df581f3 Artem Bityutskiy    2008-12-04  609  		mutex_unlock(&ubi->buf_mutex);
111ab0b2 Richard Weinberger  2014-11-10  610  		up_read(&ubi->fm_eba_sem);

:::::: The code at line 607 was first introduced by commit
:::::: 0ca39d74de8b269fb61eac11b75bd6c3fc887c28 UBI: rename peb_buf1 to peb_buf

:::::: TO: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
:::::: CC: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 20303 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer
  2016-02-02  2:30 ` [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer Bean Huo
  2016-02-02  3:05   ` kbuild test robot
@ 2016-02-02  3:08   ` kbuild test robot
  1 sibling, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:08 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 2369 bytes --]

Hi Bean,

[auto build test ERROR on v4.5-rc2]
[also build test ERROR on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x018-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450 HEAD 2078d3920abf1d89be7eaf087100b4482dd532dc builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/mtd/ubi/fastmap.c: In function 'ubi_write_fastmap':
>> drivers/mtd/ubi/fastmap.c:1315:9: error: too few arguments to function 'ubi_io_write'
      ret = ubi_io_write(ubi, fm_raw + (i * ubi->leb_size),
            ^
   In file included from drivers/mtd/ubi/fastmap.c:18:0:
   drivers/mtd/ubi/ubi.h:883:5: note: declared here
    int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
        ^

vim +/ubi_io_write +1315 drivers/mtd/ubi/fastmap.c

dbb7d2a88 Richard Weinberger 2012-09-26  1309  				new_fm->e[i]->pnum);
dbb7d2a88 Richard Weinberger 2012-09-26  1310  			goto out_kfree;
dbb7d2a88 Richard Weinberger 2012-09-26  1311  		}
dbb7d2a88 Richard Weinberger 2012-09-26  1312  	}
dbb7d2a88 Richard Weinberger 2012-09-26  1313  
dbb7d2a88 Richard Weinberger 2012-09-26  1314  	for (i = 0; i < new_fm->used_blocks; i++) {
dbb7d2a88 Richard Weinberger 2012-09-26 @1315  		ret = ubi_io_write(ubi, fm_raw + (i * ubi->leb_size),
dbb7d2a88 Richard Weinberger 2012-09-26  1316  			new_fm->e[i]->pnum, ubi->leb_start, ubi->leb_size);
dbb7d2a88 Richard Weinberger 2012-09-26  1317  		if (ret) {
326087033 Tanya Brokhman     2014-10-20  1318  			ubi_err(ubi, "unable to write fastmap to PEB %i!",

:::::: The code at line 1315 was first introduced by commit
:::::: dbb7d2a88d2a7bd3624e090bee42cdee048d9290 UBI: Add fastmap core

:::::: TO: Richard Weinberger <richard@nod.at>
:::::: CC: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 25801 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 14/17] drivers:mtd:ubi:add backup operation in ubi_io_write
  2016-02-02  2:30 ` [PATCH v2 14/17] drivers:mtd:ubi:add backup operation in ubi_io_write Bean Huo
@ 2016-02-02  3:22   ` kbuild test robot
  0 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:22 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 1961 bytes --]

Hi Bean,

[auto build test WARNING on v4.5-rc2]
[also build test WARNING on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x012-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/mtd/ubi/io.c: In function 'ubi_io_write':
>> drivers/mtd/ubi/io.c:242:6: warning: unused variable 'skip' [-Wunused-variable]
     int skip;
         ^

vim +/skip +242 drivers/mtd/ubi/io.c

   226	 *
   227	 * This function writes @len bytes of data from buffer @buf to offset @offset
   228	 * of physical eraseblock @pnum. If all the data were successfully written,
   229	 * zero is returned. If an error occurred, this function returns a negative
   230	 * error code. If %-EIO is returned, the physical eraseblock most probably went
   231	 * bad.
   232	 *
   233	 * Note, in case of an error, it is possible that something was still written
   234	 * to the flash media, but may be some garbage.
   235	 */
   236	int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
   237			 int len, int safeguard)
   238	{
   239		int err;
   240		size_t retlen;
   241		loff_t addr;
 > 242		int skip;
   243	
   244		dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset);
   245	
   246		ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
   247		ubi_assert(offset >= 0 && offset + len <= ubi->peb_size);
   248		ubi_assert(offset % ubi->hdrs_min_io_size == 0);
   249		ubi_assert(len > 0 && len % ubi->hdrs_min_io_size == 0);
   250	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 20303 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
@ 2016-02-02  3:22   ` kbuild test robot
  2016-02-02  3:56   ` kbuild test robot
  2016-02-02  3:58   ` kbuild test robot
  2 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:22 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 3159 bytes --]

Hi Bean,

[auto build test WARNING on v4.5-rc2]
[also build test WARNING on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: sparc64-allyesconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

   drivers/mtd/ubi/io.c: In function 'ubi_io_write':
>> drivers/mtd/ubi/io.c:321:5: warning: format '%d' expects argument of type 'int', but argument 4 has type 'size_t' [-Wformat=]
        ubi_err(ubi, "Written %d bytes", retlen);
        ^

vim +321 drivers/mtd/ubi/io.c

d6f52420 Bean Huo            2016-02-02  305  			if (len_temp/ubi->min_io_size)
d6f52420 Bean Huo            2016-02-02  306  				writelen = ubi->min_io_size;
d6f52420 Bean Huo            2016-02-02  307  			else
d6f52420 Bean Huo            2016-02-02  308  				writelen %= ubi->min_io_size;
d6f52420 Bean Huo            2016-02-02  309  
d6f52420 Bean Huo            2016-02-02  310  			if (is_backup_need(ubi, addr_temp)) {
d6f52420 Bean Huo            2016-02-02  311  				err = ubi_duplicate_data_to_bakvol(ubi,
d6f52420 Bean Huo            2016-02-02  312  					addr_temp, writelen, &retlen, buf_temp);
d6f52420 Bean Huo            2016-02-02  313  				} else
d6f52420 Bean Huo            2016-02-02  314  				err = mtd_write(ubi->mtd, addr_temp, writelen,
d6f52420 Bean Huo            2016-02-02  315  						&retlen, buf_temp);
d6f52420 Bean Huo            2016-02-02  316  
801c135c Artem B. Bityutskiy 2006-06-27  317  			if (err) {
d6f52420 Bean Huo            2016-02-02  318  				ubi_err(ubi, "Writing %d byptes to PEB %d:%d",
d6f52420 Bean Huo            2016-02-02  319  					writelen, pnum, offset);
d6f52420 Bean Huo            2016-02-02  320  				ubi_err(ubi, "Error %d", err);
d6f52420 Bean Huo            2016-02-02 @321  				ubi_err(ubi, "Written %d bytes", retlen);
d6f52420 Bean Huo            2016-02-02  322  				dump_stack();
d6f52420 Bean Huo            2016-02-02  323  				ubi_dump_flash(ubi, pnum, offset, writelen);
d6f52420 Bean Huo            2016-02-02  324  				} else
d6f52420 Bean Huo            2016-02-02  325  				ubi_assert(retlen == writelen);
d6f52420 Bean Huo            2016-02-02  326  		}
d6f52420 Bean Huo            2016-02-02  327  	} else
d6f52420 Bean Huo            2016-02-02  328  #endif
d6f52420 Bean Huo            2016-02-02  329  	{

:::::: The code at line 321 was first introduced by commit
:::::: d6f5242053d5a5125b0c80134fb017a3ce027d55 drivers:mtd:ubi:add backup operation in ubi_io_write

:::::: TO: Bean Huo <beanhuo@micron.com>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 45115 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
  2016-02-02  3:22   ` kbuild test robot
@ 2016-02-02  3:56   ` kbuild test robot
  2016-02-02  3:58   ` kbuild test robot
  2 siblings, 0 replies; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:56 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

[-- Attachment #1: Type: text/plain, Size: 3778 bytes --]

Hi Bean,

[auto build test WARNING on v4.5-rc2]
[also build test WARNING on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
   In file included from include/linux/printk.h:6:0,
                    from include/linux/kernel.h:13,
                    from include/linux/list.h:8,
                    from drivers/mtd/ubi/bakvol.c:35:
   drivers/mtd/ubi/bakvol.c: In function 'ubi_duplicate_data_to_bakvol':
   include/linux/kern_levels.h:4:18: warning: format '%d' expects argument of type 'int', but argument 5 has type 'size_t {aka long unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:10:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^
   include/linux/printk.h:252:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^
   drivers/mtd/ubi/ubi.h:59:32: note: in expansion of macro 'pr_err'
    #define ubi_err(ubi, fmt, ...) pr_err(UBI_NAME_STR "%d error: %s: " fmt "\n", \
                                   ^
>> drivers/mtd/ubi/bakvol.c:651:3: note: in expansion of macro 'ubi_err'
      ubi_err(ubi, "%d: Write data len overflow [%d]\n",
      ^

vim +/ubi_err +651 drivers/mtd/ubi/bakvol.c

3b3521fb Bean Huo 2016-02-02  635   * @buf: data buffer, points to data that should be programmed
3b3521fb Bean Huo 2016-02-02  636   */
3b3521fb Bean Huo 2016-02-02  637  int ubi_duplicate_data_to_bakvol(struct ubi_device *ubi, loff_t addr,
3b3521fb Bean Huo 2016-02-02  638  				size_t len, size_t *retlen, const void *buf)
3b3521fb Bean Huo 2016-02-02  639  {
3b3521fb Bean Huo 2016-02-02  640  	struct ubi_bkblk_tbl *backup_info = ubi->bkblk_tbl;
3b3521fb Bean Huo 2016-02-02  641  	struct mtd_info *mtd = ubi->mtd;
3b3521fb Bean Huo 2016-02-02  642  	int err = 0, nobak = 0;
3b3521fb Bean Huo 2016-02-02  643  	int pnum;
3b3521fb Bean Huo 2016-02-02  644  	u8 oppe_plane;
3b3521fb Bean Huo 2016-02-02  645  	loff_t lpage_addr; /* Lower page byte address */
3b3521fb Bean Huo 2016-02-02  646  	struct ubi_bkblk_info *pbk;
3b3521fb Bean Huo 2016-02-02  647  	int page_num;
3b3521fb Bean Huo 2016-02-02  648  	struct bakvol_oob_info *oob_bak = NULL, *oob_src = NULL;
3b3521fb Bean Huo 2016-02-02  649  
3b3521fb Bean Huo 2016-02-02  650  	if (len > ubi->min_io_size) {
3b3521fb Bean Huo 2016-02-02 @651  		ubi_err(ubi, "%d: Write data len overflow [%d]\n",
3b3521fb Bean Huo 2016-02-02  652  							__LINE__, len);
3b3521fb Bean Huo 2016-02-02  653  		return -EROFS;
3b3521fb Bean Huo 2016-02-02  654  	}
3b3521fb Bean Huo 2016-02-02  655  
3b3521fb Bean Huo 2016-02-02  656  	if (!buf) {
3b3521fb Bean Huo 2016-02-02  657  		ubi_err(ubi, "%d: Write buf is NULL!\n", __LINE__);
3b3521fb Bean Huo 2016-02-02  658  		return -EROFS;
3b3521fb Bean Huo 2016-02-02  659  

:::::: The code at line 651 was first introduced by commit
:::::: 3b3521fb6dda26424b36620d13e0195a5b4930b0 driver:mtd:ubi:add new bakvol module in ubi layer

:::::: TO: Bean Huo <beanhuo@micron.com>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 53141 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
  2016-02-02  3:22   ` kbuild test robot
  2016-02-02  3:56   ` kbuild test robot
@ 2016-02-02  3:58   ` kbuild test robot
  2016-02-02  4:15     ` Bean Huo 霍斌斌 (beanhuo)
  2 siblings, 1 reply; 33+ messages in thread
From: kbuild test robot @ 2016-02-02  3:58 UTC (permalink / raw)
  To: Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, beanhuo, linux-mtd, linux-kernel, zszubbocsev,
	peterpandong

Hi Bean,

[auto build test WARNING on v4.5-rc2]
[also build test WARNING on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450


coccinelle warnings: (new ones prefixed by >>)

>> drivers/mtd/ubi/bakvol.c:862:17-28: ERROR: ubi -> bkblk_tbl is NULL but dereferenced.
--
>> drivers/mtd/ubi/bakvol.c:1211:1-15: ERROR: reference preceded by free on line 1210
   drivers/mtd/ubi/bakvol.c:862:1-15: ERROR: reference preceded by free on line 855

vim +862 drivers/mtd/ubi/bakvol.c

3b3521fb Bean Huo 2016-02-02  846  out0:
3b3521fb Bean Huo 2016-02-02  847  	kfree(oob_ops_src->oobbuf);
3b3521fb Bean Huo 2016-02-02  848  out_oob_ops:
3b3521fb Bean Huo 2016-02-02  849  	kfree(oob_ops_src);
3b3521fb Bean Huo 2016-02-02  850  out_obs_src:
3b3521fb Bean Huo 2016-02-02  851  	kfree(oob_ops_bak->oobbuf);
3b3521fb Bean Huo 2016-02-02  852  out_back_oob_ops:
3b3521fb Bean Huo 2016-02-02  853  	kfree(oob_ops_bak);
3b3521fb Bean Huo 2016-02-02  854  out_backup_info:
3b3521fb Bean Huo 2016-02-02  855  	kfree(ubi->bkblk_tbl);
3b3521fb Bean Huo 2016-02-02  856  out_vidh:
3b3521fb Bean Huo 2016-02-02  857  	ubi_free_vid_hdr(ubi, vidh);
3b3521fb Bean Huo 2016-02-02  858  out_ech:
3b3521fb Bean Huo 2016-02-02  859  	kfree(ech);
3b3521fb Bean Huo 2016-02-02  860  out_init:
3b3521fb Bean Huo 2016-02-02  861  	ubi_err(ubi, "bakvol module init error,init step [%d].\n", step);
3b3521fb Bean Huo 2016-02-02 @862  	ubi->bkblk_tbl->bakvol_flag = UBI_BAKVOL_REJECT;
3b3521fb Bean Huo 2016-02-02  863  	return -1;
3b3521fb Bean Huo 2016-02-02  864  }
3b3521fb Bean Huo 2016-02-02  865  
3b3521fb Bean Huo 2016-02-02  866  /**
3b3521fb Bean Huo 2016-02-02  867   * ubi_bakvol_peb_scan - check VID header,see if this PEB
3b3521fb Bean Huo 2016-02-02  868   *				belongs to bakvol
3b3521fb Bean Huo 2016-02-02  869   *
3b3521fb Bean Huo 2016-02-02  870   * This function returns 1 if this PEB not belongs to bakvol

:::::: The code at line 862 was first introduced by commit
:::::: 3b3521fb6dda26424b36620d13e0195a5b4930b0 driver:mtd:ubi:add new bakvol module in ubi layer

:::::: TO: Bean Huo <beanhuo@micron.com>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  3:58   ` kbuild test robot
@ 2016-02-02  4:15     ` Bean Huo 霍斌斌 (beanhuo)
  2016-02-03  0:46       ` Brian Norris
  0 siblings, 1 reply; 33+ messages in thread
From: Bean Huo 霍斌斌 (beanhuo) @ 2016-02-02  4:15 UTC (permalink / raw)
  To: kbuild test robot, Bean Huo
  Cc: kbuild-all, richard, dedekind1, adrian.hunter, computersforpeace,
	boris.brezillon, linux-mtd, linux-kernel,
	Zoltan Szubbocsev (zszubbocsev),
	Peter Pan 潘栋 (peterpandong)

> Hi Bean,
> 
> [auto build test WARNING on v4.5-rc2]

This version 2.0 patches are based on 4.2-rc7.

> [also build test WARNING on next-20160201] [if your patch is applied to the
> wrong git tree, please drop us a note to help improving the system]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
  2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
                   ` (16 preceding siblings ...)
  2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
@ 2016-02-02 23:06 ` Richard Weinberger
  2016-02-03  6:11     ` Bean Huo 霍斌斌 (beanhuo)
  17 siblings, 1 reply; 33+ messages in thread
From: Richard Weinberger @ 2016-02-02 23:06 UTC (permalink / raw)
  To: Bean Huo, dedekind1, adrian.hunter, computersforpeace, boris.brezillon
  Cc: beanhuo, linux-mtd, linux-kernel, zszubbocsev, peterpandong

Bean,

Am 02.02.2016 um 03:30 schrieb Bean Huo:
> This version patches based on Linux kernel 4.2-rc7.
>  
>  v2:
>    1.Add CRC32 protection for user OOB area data.
>    2.Move recovery action from attach step to ubifs mount step.
>    3.Add more comments for some key function.
>    4.standard multi-plane program function.
>    5.Standard send-mail patches

It is sad to see that you've ignored almost all review comments that have been made.
Both comments made by Boris and me on the public mailing list as well as the comments
and I made on our phone call.

To summarize, I see the following major issues with this patch series:
1. It makes use of OOB, it was very clearly stated that this violates one of UBI's design principles.

2. It is not generic, you use hard coded constants for Micron 70s/80s MLC NANDs.
   And AFAICT it is not guaranteed that all MLC NANDs support multi pane writes.

3. Not all data is protected. Most of UBI's meta data (EC&VID headers, volume table)
   are explicitly not protected, as well as UBIFS's superblock and master nodes.

4. It mixes UBI and UBIFS code. Having code like this in UBI's EBA code is not acceptable:
   ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
   This hack is here to void safe writes of UBIFS's suberblock and master nodes.
   But UBIFS specific code has no business in UBI core code. Also See 3.

5. It does not scale. Having a backup of every important page would require much more space.
   Especially UBI EC and VID headers. I bet this is also the reason why the current implementation
   does not protect them. Otherwise the bakvol would fill up immediately.
   Another scalability problem is that the whole bakvol has to be scanned which will slow down
   the attach/mount process and may void the speedup gained by Fastmap.

6. It focuses only on UBIFS. ubi_corrupted_data_recovery() is only called from UBIFS code.
   If UBI is changed, we need a solution for all users on top of UBI.
   Now I understand also why you want the "fs:ubifs:recovery:fixup UBIFS cannot recover master node issue"
   patch. As UBIFS master nodes are not protected by bakvol they will corrupt and UBIFS is not able to recover
   nor can run ubi_corrupted_data_recovery().

7. A full bakvol is not proper handled. The implementation falls back to "unsafe" writes.
                dbg_gen("Allocate new PEB for Bakvol.\n");
                pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
                if (!pbk) {
                        ubi_err(ubi, "Allocate new PEB failed.\n");
                        nobak = 1;
                        goto Only_source;
                }
   You cannot expect users to query the kernel log for such error messages.


Beside of these issues there are a lot of small implementation issues.
For example Fastmap is broken as UBI_FM_SB_VOLUME_ID clashes with UBI_BACKUP_VOLUME_ID.
Or struct list_head is part of on-Flash data structures.

That said, it don't think the bakvol approach is the solution we're looking for.
A proper solution has to fulfill the following conditions:
1. No dependency on OOB data.
2. Can work with any MLC NANDs and controllers. Boris and I have access to Hynix, Micron and Toshiba NAND so far.
3. If implemented on UBI level, it has to work for any user on top of UBI.
4. Has to be able to protect all data.
5. Must not regress current UBI or UBIFS.

Boris and I are working on such a solution and would like to invite you to join us.
The topic is complicated and not easy to solve. But with joined forces we will be able
to find a good solution. :-)

Thanks,
//richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-02  4:15     ` Bean Huo 霍斌斌 (beanhuo)
@ 2016-02-03  0:46       ` Brian Norris
  2016-02-03  6:14         ` Bean Huo 霍斌斌 (beanhuo)
  0 siblings, 1 reply; 33+ messages in thread
From: Brian Norris @ 2016-02-03  0:46 UTC (permalink / raw)
  To: Bean Huo 霍斌斌 (beanhuo)
  Cc: kbuild test robot, Bean Huo, kbuild-all, richard, dedekind1,
	adrian.hunter, boris.brezillon, linux-mtd, linux-kernel,
	Zoltan Szubbocsev (zszubbocsev),
	Peter Pan 潘栋 (peterpandong)

On Tue, Feb 02, 2016 at 04:15:43AM +0000, Bean Huo 霍斌斌 wrote:
> > Hi Bean,
> > 
> > [auto build test WARNING on v4.5-rc2]
> 
> This version 2.0 patches are based on 4.2-rc7.

Please don't send patches against ancient kernel versions.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
  2016-02-02 23:06 ` [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Richard Weinberger
@ 2016-02-03  6:11     ` Bean Huo 霍斌斌 (beanhuo)
  0 siblings, 0 replies; 33+ messages in thread
From: Bean Huo 霍斌斌 (beanhuo) @ 2016-02-03  6:11 UTC (permalink / raw)
  To: Richard Weinberger, Bean Huo, dedekind1, adrian.hunter,
	computersforpeace, boris.brezillon
  Cc: linux-mtd, linux-kernel, Zoltan Szubbocsev (zszubbocsev),
	Peter Pan 潘栋 (peterpandong)

Dear Richard
Thanks for reviewing my patches and valuable feedback. 
I also want to work with you and Boris on such solution, 
I know this is a complicated task, need our joint effort.

Following is my explanation for each of concerns:

> Bean,
> 
> Am 02.02.2016 um 03:30 schrieb Bean Huo:
> > This version patches based on Linux kernel 4.2-rc7.
> >
> >  v2:
> >    1.Add CRC32 protection for user OOB area data.
> >    2.Move recovery action from attach step to ubifs mount step.
> >    3.Add more comments for some key function.
> >    4.standard multi-plane program function.
> >    5.Standard send-mail patches
> 
> It is sad to see that you've ignored almost all review comments that have
> been made.
> Both comments made by Boris and me on the public mailing list as well as the
> comments and I made on our phone call.
> 
> To summarize, I see the following major issues with this patch series:
> 1. It makes use of OOB, it was very clearly stated that this violates one of
> UBI's design principles.
Currently I still cannot find a good method on how to manage backup info.
So now I still use OOB.
Backup page OOB stores source page address, and source page OOB store backup page address,
They store each other's page address, one is in order to indicate that backup page
is really one copy data of source page, in case of source block being erased and re-mapped again.
Another is in order to quickly find corresponding source page.

> 2. It is not generic, you use hard coded constants for Micron 70s/80s MLC
> NANDs.
>    And AFAICT it is not guaranteed that all MLC NANDs support multi pane
> writes.
Yes, so far ,different NAND vendor with different paired page sequence,
So if guarantee all vendor NAND, should involve every vendor NAND paired page
Sequence table or calculator function, but now I don't have other NAND vendor 
datasheet.

> 3. Not all data is protected. Most of UBI's meta data (EC&VID headers,
> volume table)
>    are explicitly not protected, as well as UBIFS's superblock and master
> nodes.
For master node: 
current UBIFS master node already has one copy for power loss,
Just not cover MLC paired page power loss issue, if my previous Master node issue 
patch be accepted, master node totally does not need to protection.

EC&VID:
For EC header, according to my testing result data and our NAND PE cycle requirement,
If EC header be damaged by power loss , mean erase count is ok, no impact on NAND life.
But for VID header, because my solution uses dual plane page program, it has special page address
Requirement on dual plane page address, that is page number should be the same.
UBI already pre-program page 0 and page 1, so no page 1 is for VID.


> 4. It mixes UBI and UBIFS code. Having code like this in UBI's EBA code is not
> acceptable:
>    ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
>    This hack is here to void safe writes of UBIFS's suberblock and master
> nodes.
>    But UBIFS specific code has no business in UBI core code. Also See 3.
These codes need to modify. Thanks.

> 5. It does not scale. Having a backup of every important page would require
> much more space.
>    Especially UBI EC and VID headers. I bet this is also the reason why the
> current implementation
>    does not protect them. Otherwise the bakvol would fill up immediately.
>    Another scalability problem is that the whole bakvol has to be scanned
> which will slow down
>    the attach/mount process and may void the speedup gained by Fastmap.
This is also my concern, maybe next version I can fix this by store bakvol PEB info
Into flash.

> 6. It focuses only on UBIFS. ubi_corrupted_data_recovery() is only called
> from UBIFS code.
>    If UBI is changed, we need a solution for all users on top of UBI.
>    Now I understand also why you want the "fs:ubifs:recovery:fixup UBIFS
> cannot recover master node issue"
>    patch. As UBIFS master nodes are not protected by bakvol they will
> corrupt and UBIFS is not able to recover
>    nor can run ubi_corrupted_data_recovery().
> 
> 7. A full bakvol is not proper handled. The implementation falls back to
> "unsafe" writes.
>                 dbg_gen("Allocate new PEB for Bakvol.\n");
>                 pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
>                 if (!pbk) {
>                         ubi_err(ubi, "Allocate new PEB failed.\n");
>                         nobak = 1;
>                         goto Only_source;
>                 }
>    You cannot expect users to query the kernel log for such error messages.
> 
> 
> Beside of these issues there are a lot of small implementation issues.
> For example Fastmap is broken as UBI_FM_SB_VOLUME_ID clashes with
> UBI_BACKUP_VOLUME_ID.
> Or struct list_head is part of on-Flash data structures.
> 
> That said, it don't think the bakvol approach is the solution we're looking for.
> A proper solution has to fulfill the following conditions:
> 1. No dependency on OOB data.
> 2. Can work with any MLC NANDs and controllers. Boris and I have access to
> Hynix, Micron and Toshiba NAND so far.
> 3. If implemented on UBI level, it has to work for any user on top of UBI.
> 4. Has to be able to protect all data.
> 5. Must not regress current UBI or UBIFS.
> 
> Boris and I are working on such a solution and would like to invite you to join
> us.
> The topic is complicated and not easy to solve. But with joined forces we will
> be able to find a good solution. :-)
Look forward to work with you for this.

> Thanks,
> //richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
@ 2016-02-03  6:11     ` Bean Huo 霍斌斌 (beanhuo)
  0 siblings, 0 replies; 33+ messages in thread
From: Bean Huo 霍斌斌 (beanhuo) @ 2016-02-03  6:11 UTC (permalink / raw)
  To: Richard Weinberger, Bean Huo, dedekind1, adrian.hunter,
	computersforpeace, boris.brezillon
  Cc: linux-mtd, linux-kernel, Zoltan Szubbocsev (zszubbocsev),
	Peter Pan 潘栋 (peterpandong)

Dear Richard
Thanks for reviewing my patches and valuable feedback. 
I also want to work with you and Boris on such solution, 
I know this is a complicated task, need our joint effort.

Following is my explanation for each of concerns:

> Bean,
> 
> Am 02.02.2016 um 03:30 schrieb Bean Huo:
> > This version patches based on Linux kernel 4.2-rc7.
> >
> >  v2:
> >    1.Add CRC32 protection for user OOB area data.
> >    2.Move recovery action from attach step to ubifs mount step.
> >    3.Add more comments for some key function.
> >    4.standard multi-plane program function.
> >    5.Standard send-mail patches
> 
> It is sad to see that you've ignored almost all review comments that have
> been made.
> Both comments made by Boris and me on the public mailing list as well as the
> comments and I made on our phone call.
> 
> To summarize, I see the following major issues with this patch series:
> 1. It makes use of OOB, it was very clearly stated that this violates one of
> UBI's design principles.
Currently I still cannot find a good method on how to manage backup info.
So now I still use OOB.
Backup page OOB stores source page address, and source page OOB store backup page address,
They store each other's page address, one is in order to indicate that backup page
is really one copy data of source page, in case of source block being erased and re-mapped again.
Another is in order to quickly find corresponding source page.

> 2. It is not generic, you use hard coded constants for Micron 70s/80s MLC
> NANDs.
>    And AFAICT it is not guaranteed that all MLC NANDs support multi pane
> writes.
Yes, so far ,different NAND vendor with different paired page sequence,
So if guarantee all vendor NAND, should involve every vendor NAND paired page
Sequence table or calculator function, but now I don't have other NAND vendor 
datasheet.

> 3. Not all data is protected. Most of UBI's meta data (EC&VID headers,
> volume table)
>    are explicitly not protected, as well as UBIFS's superblock and master
> nodes.
For master node: 
current UBIFS master node already has one copy for power loss,
Just not cover MLC paired page power loss issue, if my previous Master node issue 
patch be accepted, master node totally does not need to protection.

EC&VID:
For EC header, according to my testing result data and our NAND PE cycle requirement,
If EC header be damaged by power loss , mean erase count is ok, no impact on NAND life.
But for VID header, because my solution uses dual plane page program, it has special page address
Requirement on dual plane page address, that is page number should be the same.
UBI already pre-program page 0 and page 1, so no page 1 is for VID.


> 4. It mixes UBI and UBIFS code. Having code like this in UBI's EBA code is not
> acceptable:
>    ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
>    This hack is here to void safe writes of UBIFS's suberblock and master
> nodes.
>    But UBIFS specific code has no business in UBI core code. Also See 3.
These codes need to modify. Thanks.

> 5. It does not scale. Having a backup of every important page would require
> much more space.
>    Especially UBI EC and VID headers. I bet this is also the reason why the
> current implementation
>    does not protect them. Otherwise the bakvol would fill up immediately.
>    Another scalability problem is that the whole bakvol has to be scanned
> which will slow down
>    the attach/mount process and may void the speedup gained by Fastmap.
This is also my concern, maybe next version I can fix this by store bakvol PEB info
Into flash.

> 6. It focuses only on UBIFS. ubi_corrupted_data_recovery() is only called
> from UBIFS code.
>    If UBI is changed, we need a solution for all users on top of UBI.
>    Now I understand also why you want the "fs:ubifs:recovery:fixup UBIFS
> cannot recover master node issue"
>    patch. As UBIFS master nodes are not protected by bakvol they will
> corrupt and UBIFS is not able to recover
>    nor can run ubi_corrupted_data_recovery().
> 
> 7. A full bakvol is not proper handled. The implementation falls back to
> "unsafe" writes.
>                 dbg_gen("Allocate new PEB for Bakvol.\n");
>                 pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
>                 if (!pbk) {
>                         ubi_err(ubi, "Allocate new PEB failed.\n");
>                         nobak = 1;
>                         goto Only_source;
>                 }
>    You cannot expect users to query the kernel log for such error messages.
> 
> 
> Beside of these issues there are a lot of small implementation issues.
> For example Fastmap is broken as UBI_FM_SB_VOLUME_ID clashes with
> UBI_BACKUP_VOLUME_ID.
> Or struct list_head is part of on-Flash data structures.
> 
> That said, it don't think the bakvol approach is the solution we're looking for.
> A proper solution has to fulfill the following conditions:
> 1. No dependency on OOB data.
> 2. Can work with any MLC NANDs and controllers. Boris and I have access to
> Hynix, Micron and Toshiba NAND so far.
> 3. If implemented on UBI level, it has to work for any user on top of UBI.
> 4. Has to be able to protect all data.
> 5. Must not regress current UBI or UBIFS.
> 
> Boris and I are working on such a solution and would like to invite you to join
> us.
> The topic is complicated and not easy to solve. But with joined forces we will
> be able to find a good solution. :-)
Look forward to work with you for this.

> Thanks,
> //richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile
  2016-02-03  0:46       ` Brian Norris
@ 2016-02-03  6:14         ` Bean Huo 霍斌斌 (beanhuo)
  0 siblings, 0 replies; 33+ messages in thread
From: Bean Huo 霍斌斌 (beanhuo) @ 2016-02-03  6:14 UTC (permalink / raw)
  To: Brian Norris
  Cc: kbuild test robot, Bean Huo, kbuild-all, richard, dedekind1,
	adrian.hunter, boris.brezillon, linux-mtd, linux-kernel,
	Zoltan Szubbocsev (zszubbocsev),
	Peter Pan 潘栋 (peterpandong)

> >On Tue, Feb 02, 2016 at 04:15:43AM +0000, Bean Huo 霍斌斌 wrote:
> > > Hi Bean,
> > >
> > > [auto build test WARNING on v4.5-rc2]
> >
> > This version 2.0 patches are based on 4.2-rc7.
> 
> Please don't send patches against ancient kernel versions.
Brian 
Sorry for this. this patches codes are too long,
Next time I will push my patches based on latest kernel.

Beat Regards!
Beanhuo

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2016-02-03  6:15 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02  2:30 [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo
2016-02-02  2:30 ` [PATCH v2 01/17] include:mtd:add multi-plane page program command Bean Huo
2016-02-02  2:30 ` [PATCH v2 02/17] include:mtd:add multi-plane program in mtd_info Bean Huo
2016-02-02  2:30 ` [PATCH v2 03/17] drivers:mtd:add dual plane page program support in partition layer Bean Huo
2016-02-02  3:00   ` kbuild test robot
2016-02-02  2:30 ` [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function Bean Huo
2016-02-02  3:04   ` kbuild test robot
2016-02-02  2:30 ` [PATCH v2 05/17] drivers:mtd:ubi:add bakvol on-flash and RAM data structures Bean Huo
2016-02-02  2:30 ` [PATCH v2 06/17] drivers:mtd:ubi:add bakvol function define in ubi layer Bean Huo
2016-02-02  3:05   ` kbuild test robot
2016-02-02  3:08   ` kbuild test robot
2016-02-02  2:30 ` [PATCH v2 07/17] fs:ubifs:add bakvol function define in ubifs layer Bean Huo
2016-02-02  2:30 ` [PATCH v2 08/17] drivers:mtd:ubi:disable bakvol function while writing volume table Bean Huo
2016-02-02  2:30 ` [PATCH v2 09/17] drivers:mtd:ubi:get PEB according to specfied plane number Bean Huo
2016-02-02  2:30 ` [PATCH v2 10/17] drivers:mtd:ubi:enable bakvol function for fastmap operation Bean Huo
2016-02-02  2:30 ` [PATCH v2 11/17] drivers:mtd:ubi:add disable/enable bakvol while ubi write Bean Huo
2016-02-02  2:30 ` [PATCH v2 12/17] drivers:mtd:ubi:add disable bakvol while ubi detach Bean Huo
2016-02-02  2:30 ` [PATCH v2 13/17] drivers:mtd:ubi:add bakvol init while attach ubi Bean Huo
2016-02-02  2:30 ` [PATCH v2 14/17] drivers:mtd:ubi:add backup operation in ubi_io_write Bean Huo
2016-02-02  3:22   ` kbuild test robot
2016-02-02  2:30 ` [PATCH v2 15/17] fs:ubifs:enable bakvol module and recover operation Bean Huo
2016-02-02  2:30   ` Bean Huo
2016-02-02  2:30 ` [PATCH v2 16/17] driver:mtd:ubi:add new bakvol module in ubi layer Bean Huo
2016-02-02  2:30 ` [PATCH v2 17/17] drivers:mtd:ubi: Kconfig Makefile Bean Huo
2016-02-02  3:22   ` kbuild test robot
2016-02-02  3:56   ` kbuild test robot
2016-02-02  3:58   ` kbuild test robot
2016-02-02  4:15     ` Bean Huo 霍斌斌 (beanhuo)
2016-02-03  0:46       ` Brian Norris
2016-02-03  6:14         ` Bean Huo 霍斌斌 (beanhuo)
2016-02-02 23:06 ` [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Richard Weinberger
2016-02-03  6:11   ` Bean Huo 霍斌斌 (beanhuo)
2016-02-03  6:11     ` Bean Huo 霍斌斌 (beanhuo)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.