Patchwork ubi: add volume id and LEB number to struct ubi_scan_leb

login
register
mail settings
Submitter Joel Reardon
Date May 16, 2012, 12:20 p.m.
Message ID <alpine.DEB.2.00.1205161419590.27131@eristoteles.iwoars.net>
Download mbox | patch
Permalink /patch/159613/
State New
Headers show

Comments

Joel Reardon - May 16, 2012, 12:20 p.m.
This patch adds the volume id and LEB number to struct ubi_scan_leb when
scanning the LEBs at startup.  PEBs now added to the erase queue will know
their original LEB number and volume id, if available, and will be -1
otherwise (for instance, if the vid header is unreadable).

This was tested by creating an ubi device with 3 volumes and disabiling the
ubi_thread's do_work functionality. The different ubi volumes were formatted
to ubifs and had files created and erased.  The ubi modules was reloaded and
the list of LEB's added to the erased list was outputted, confirming the
volume ids and LEB numbers were appropriate.

Signed-off-by: Joel Reardon <reardonj@inf.ethz.ch>
---
 drivers/mtd/ubi/scan.c |   49 +++++++++++++++++++++++++++++------------------
 drivers/mtd/ubi/scan.h |    2 +
 2 files changed, 32 insertions(+), 19 deletions(-)
Artem Bityutskiy - May 16, 2012, 2:34 p.m.
On Wed, 2012-05-16 at 14:20 +0200, Joel Reardon wrote:
> This patch adds the volume id and LEB number to struct ubi_scan_leb when
> scanning the LEBs at startup.  PEBs now added to the erase queue will know
> their original LEB number and volume id, if available, and will be -1
> otherwise (for instance, if the vid header is unreadable).
> 
> This was tested by creating an ubi device with 3 volumes and disabiling the
> ubi_thread's do_work functionality. The different ubi volumes were formatted
> to ubifs and had files created and erased.  The ubi modules was reloaded and
> the list of LEB's added to the erased list was outputted, confirming the
> volume ids and LEB numbers were appropriate.
> 
> Signed-off-by: Joel Reardon <reardonj@inf.ethz.ch>

I've added this code to the joel branch. But please, test this and other
UBI merge candidates with all the UBI debugging checks enabled as well.
Similar to UBIFS.

Well, I mean, I am willing to merge this feature upstream as soon as it
is in good shape, even if your crypto code is never merged. So testing
with debugging enabled should be done. For various small patches you
send which will land in the joel branch - I do not care much - test with
debugging enabled just sometimes.

Anyway, this patch is in "joel", once the whole features is there, I'll
move it to "master". So you could give this feature more priority for
now.
Artem Bityutskiy - May 16, 2012, 2:49 p.m.
On Wed, 2012-05-16 at 17:34 +0300, Artem Bityutskiy wrote:
> I've added this code to the joel branch. But please, test this and
> other
> UBI merge candidates with all the UBI debugging checks enabled as
> well.
> Similar to UBIFS. 

To do this:

1. Mount debugfs, in my Fedora it is already mounted:

sudo mount -t debugfs none /sys/kernel/debug/


Then:

$cd /sys/kernel/debug/ubi/ubi0
$sudo sh -c 'echo 1 > chk_gen'
$sudo sh -c 'echo 1 > chk_io'

This will enable "general" and "IO" extra self-checks for UBI device
"ubi0"

Patch

diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index c26b1ad..3d87446 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -102,20 +102,23 @@  static struct ubi_vid_hdr *vidh;
  * add_to_list - add physical eraseblock to a list.
  * @si: scanning information
  * @pnum: physical eraseblock number to add
+ * @vol_id: the last used volume id for the PEB
+ * @lnum: the last used LEB number for the PEB
  * @ec: erase counter of the physical eraseblock
  * @to_head: if not zero, add to the head of the list
  * @list: the list to add to
  *
  * This function adds physical eraseblock @pnum to free, erase, or alien lists.
- * If @to_head is not zero, PEB will be added to the head of the list, which
- * basically means it will be processed first later. E.g., we add corrupted
- * PEBs (corrupted due to power cuts) to the head of the erase list to make
- * sure we erase them first and get rid of corruptions ASAP. This function
- * returns zero in case of success and a negative error code in case of
- * failure.
+ * It stores the @lnum and @vol_id alongside, which can both be -1 if they are
+ * not available, not readable, or not assigned. If @to_head is not zero, PEB
+ * will be added to the head of the list, which basically means it will be
+ * processed first later. E.g., we add corrupted PEBs (corrupted due to power
+ * cuts) to the head of the erase list to make sure we erase them first and
+ * get rid of corruptions ASAP. This function returns zero in case of success
+ * and a negative error code in case of failure.
  */
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
-		       struct list_head *list)
+static int add_to_list(struct ubi_scan_info *si, int pnum, int vol_id,
+		       int lnum, int ec, int to_head, struct list_head *list)
 {
 	struct ubi_scan_leb *seb;

@@ -134,6 +137,8 @@  static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
 		return -ENOMEM;

 	seb->pnum = pnum;
+	seb->vol_id = vol_id;
+	seb->lnum = lnum;
 	seb->ec = ec;
 	if (to_head)
 		list_add(&seb->u.list, list);
@@ -532,13 +537,16 @@  int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 			if (err)
 				return err;

-			err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
+			err = add_to_list(si, seb->pnum, seb->vol_id,
+					  seb->lnum, seb->ec, cmp_res & 4,
 					  &si->erase);
 			if (err)
 				return err;

 			seb->ec = ec;
 			seb->pnum = pnum;
+			seb->vol_id = vol_id;
+			seb->lnum = lnum;
 			seb->scrub = ((cmp_res & 2) || bitflips);
 			seb->copy_flag = vid_hdr->copy_flag;
 			seb->sqnum = sqnum;
@@ -553,8 +561,8 @@  int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 			 * This logical eraseblock is older than the one found
 			 * previously.
 			 */
-			return add_to_list(si, pnum, ec, cmp_res & 4,
-					   &si->erase);
+			return add_to_list(si, pnum, vol_id, lnum, ec,
+					   cmp_res & 4, &si->erase);
 		}
 	}

@@ -573,6 +581,7 @@  int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,

 	seb->ec = ec;
 	seb->pnum = pnum;
+	seb->vol_id = vol_id;
 	seb->lnum = lnum;
 	seb->scrub = bitflips;
 	seb->copy_flag = vid_hdr->copy_flag;
@@ -868,11 +877,11 @@  static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 		break;
 	case UBI_IO_FF:
 		si->empty_peb_count += 1;
-		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
+		return add_to_list(si, pnum, -1, -1, UBI_SCAN_UNKNOWN_EC, 0,
 				   &si->erase);
 	case UBI_IO_FF_BITFLIPS:
 		si->empty_peb_count += 1;
-		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
+		return add_to_list(si, pnum, -1, -1, UBI_SCAN_UNKNOWN_EC, 1,
 				   &si->erase);
 	case UBI_IO_BAD_HDR_EBADMSG:
 	case UBI_IO_BAD_HDR:
@@ -984,7 +993,7 @@  static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 			return err;
 		else if (!err)
 			/* This corruption is caused by a power cut */
-			err = add_to_list(si, pnum, ec, 1, &si->erase);
+			err = add_to_list(si, pnum, -1, -1, ec, 1, &si->erase);
 		else
 			/* This is an unexpected corruption */
 			err = add_corrupted(si, pnum, ec);
@@ -992,15 +1001,15 @@  static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 			return err;
 		goto adjust_mean_ec;
 	case UBI_IO_FF_BITFLIPS:
-		err = add_to_list(si, pnum, ec, 1, &si->erase);
+		err = add_to_list(si, pnum, -1, -1, ec, 1, &si->erase);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
 	case UBI_IO_FF:
 		if (ec_err)
-			err = add_to_list(si, pnum, ec, 1, &si->erase);
+			err = add_to_list(si, pnum, -1, -1, ec, 1, &si->erase);
 		else
-			err = add_to_list(si, pnum, ec, 0, &si->free);
+			err = add_to_list(si, pnum, -1, -1, ec, 0, &si->free);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
@@ -1019,7 +1028,8 @@  static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 		case UBI_COMPAT_DELETE:
 			ubi_msg("\"delete\" compatible internal volume %d:%d"
 				" found, will remove it", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, 1, &si->erase);
+			err = add_to_list(si, pnum, vol_id, lnum,
+					  ec, 1, &si->erase);
 			if (err)
 				return err;
 			return 0;
@@ -1034,7 +1044,8 @@  static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 		case UBI_COMPAT_PRESERVE:
 			ubi_msg("\"preserve\" compatible internal volume %d:%d"
 				" found", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, 0, &si->alien);
+			err = add_to_list(si, pnum, vol_id, lnum,
+					  ec, 0, &si->alien);
 			if (err)
 				return err;
 			return 0;
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index d48aef1..e214647 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -28,6 +28,7 @@ 
  * struct ubi_scan_leb - scanning information about a physical eraseblock.
  * @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown)
  * @pnum: physical eraseblock number
+ * @vol_id: the volume identifier of the LEB.
  * @lnum: logical eraseblock number
  * @scrub: if this physical eraseblock needs scrubbing
  * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
@@ -42,6 +43,7 @@ 
 struct ubi_scan_leb {
 	int ec;
 	int pnum;
+	int vol_id;
 	int lnum;
 	unsigned int scrub:1;
 	unsigned int copy_flag:1;