summaryrefslogtreecommitdiff
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorJoel Reardon <joel@clambassador.com>2012-05-16 16:20:56 +0400
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-05-21 12:34:41 +0400
commit6dd3bc7e6032ffb392477fadca77172c1c9e346b (patch)
tree7578223021e61398f46f84c5f4fb42300ce44d10 /drivers/mtd/ubi
parent5cc09420e2bcd75d6a8f701c60a179ebb564cb3c (diff)
downloadlinux-6dd3bc7e6032ffb392477fadca77172c1c9e346b.tar.xz
UBI: add volume id struct ubi_ainf_peb
This patch adds the volume id to struct ubi_ainf_peb 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> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/attach.c46
-rw-r--r--drivers/mtd/ubi/ubi.h5
2 files changed, 35 insertions, 16 deletions
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index f59f748caf23..bd27cbbb4066 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -99,12 +99,16 @@ static struct ubi_vid_hdr *vidh;
* add_to_list - add physical eraseblock to a list.
* @ai: attaching 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 allocates a 'struct ubi_ainf_peb' object for physical
* eraseblock @pnum and adds it to the "free", "erase", or "alien" lists.
+ * It stores the @lnum and @vol_id alongside, which can both be
+ * %UBI_UNKNOWN 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
@@ -112,8 +116,8 @@ static struct ubi_vid_hdr *vidh;
* returns zero in case of success and a negative error code in case of
* failure.
*/
-static int add_to_list(struct ubi_attach_info *ai, int pnum, int ec,
- int to_head, struct list_head *list)
+static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id,
+ int lnum, int ec, int to_head, struct list_head *list)
{
struct ubi_ainf_peb *aeb;
@@ -132,6 +136,8 @@ static int add_to_list(struct ubi_attach_info *ai, int pnum, int ec,
return -ENOMEM;
aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
aeb->ec = ec;
if (to_head)
list_add(&aeb->u.list, list);
@@ -530,13 +536,16 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
if (err)
return err;
- err = add_to_list(ai, aeb->pnum, aeb->ec, cmp_res & 4,
+ err = add_to_list(ai, aeb->pnum, aeb->vol_id,
+ aeb->lnum, aeb->ec, cmp_res & 4,
&ai->erase);
if (err)
return err;
aeb->ec = ec;
aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
aeb->scrub = ((cmp_res & 2) || bitflips);
aeb->copy_flag = vid_hdr->copy_flag;
aeb->sqnum = sqnum;
@@ -551,8 +560,8 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
* This logical eraseblock is older than the one found
* previously.
*/
- return add_to_list(ai, pnum, ec, cmp_res & 4,
- &ai->erase);
+ return add_to_list(ai, pnum, vol_id, lnum, ec,
+ cmp_res & 4, &ai->erase);
}
}
@@ -571,6 +580,7 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
aeb->ec = ec;
aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
aeb->lnum = lnum;
aeb->scrub = bitflips;
aeb->copy_flag = vid_hdr->copy_flag;
@@ -834,12 +844,12 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
break;
case UBI_IO_FF:
ai->empty_peb_count += 1;
- return add_to_list(ai, pnum, UBI_UNKNOWN, 0,
- &ai->erase);
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 0, &ai->erase);
case UBI_IO_FF_BITFLIPS:
ai->empty_peb_count += 1;
- return add_to_list(ai, pnum, UBI_UNKNOWN, 1,
- &ai->erase);
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 1, &ai->erase);
case UBI_IO_BAD_HDR_EBADMSG:
case UBI_IO_BAD_HDR:
/*
@@ -950,7 +960,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
return err;
else if (!err)
/* This corruption is caused by a power cut */
- err = add_to_list(ai, pnum, ec, 1, &ai->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
else
/* This is an unexpected corruption */
err = add_corrupted(ai, pnum, ec);
@@ -958,15 +969,18 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
return err;
goto adjust_mean_ec;
case UBI_IO_FF_BITFLIPS:
- err = add_to_list(ai, pnum, ec, 1, &ai->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ ec, 1, &ai->erase);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF:
if (ec_err)
- err = add_to_list(ai, pnum, ec, 1, &ai->erase);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
else
- err = add_to_list(ai, pnum, ec, 0, &ai->free);
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 0, &ai->free);
if (err)
return err;
goto adjust_mean_ec;
@@ -985,7 +999,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d"
" found, will remove it", vol_id, lnum);
- err = add_to_list(ai, pnum, ec, 1, &ai->erase);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 1, &ai->erase);
if (err)
return err;
return 0;
@@ -1000,7 +1015,8 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
case UBI_COMPAT_PRESERVE:
ubi_msg("\"preserve\" compatible internal volume %d:%d"
" found", vol_id, lnum);
- err = add_to_list(ai, pnum, ec, 0, &ai->alien);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 0, &ai->alien);
if (err)
return err;
return 0;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 52756327827a..b4b3913f1df4 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -483,6 +483,7 @@ struct ubi_device {
* struct ubi_ainf_peb - attach information about a physical eraseblock.
* @ec: erase counter (%UBI_UNKNOWN if it is unknown)
* @pnum: physical eraseblock number
+ * @vol_id: ID of the volume this LEB belongs to
* @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)
@@ -492,11 +493,13 @@ struct ubi_device {
* @u.list: link in one of the eraseblock lists
*
* One object of this type is allocated for each physical eraseblock when
- * attaching an MTD device.
+ * attaching an MTD device. Note, if this PEB does not belong to any LEB /
+ * volume, the @vol_id and @lnum fields are initialized to %UBI_UNKNOWN.
*/
struct ubi_ainf_peb {
int ec;
int pnum;
+ int vol_id;
int lnum;
unsigned int scrub:1;
unsigned int copy_flag:1;