From: Teresa Remmet <t.remmet@phytec.de>
To: barebox@lists.infradead.org
Subject: [PATCH 29/56] UBI: simplify LEB write and atomic LEB change code
Date: Wed, 29 Aug 2018 14:19:45 +0200 [thread overview]
Message-ID: <1535545212-18871-30-git-send-email-t.remmet@phytec.de> (raw)
In-Reply-To: <1535545212-18871-1-git-send-email-t.remmet@phytec.de>
From: Boris Brezillon <boris.brezillon@free-electrons.com>
ubi_eba_write_leb(), ubi_eba_write_leb_st() and
ubi_eba_atomic_leb_change() are using a convoluted retry/exit path.
Add the try_write_vid_and_data() function to simplify the retry logic
and make sure we have a single exit path instead of manually releasing
the resources in each error path.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
[Fix conflicts]
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
drivers/mtd/ubi/eba.c | 271 +++++++++++++++++++++-----------------------------
1 file changed, 113 insertions(+), 158 deletions(-)
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index bc2dc2ef4371..fd8368286825 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -600,6 +600,67 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
}
/**
+ * try_write_vid_and_data - try to write VID header and data to a new PEB.
+ * @vol: volume description object
+ * @lnum: logical eraseblock number
+ * @vid_hdr: VID header to write
+ * @buf: buffer containing the data
+ * @offset: where to start writing data
+ * @len: how many bytes should be written
+ *
+ * This function tries to write VID header and data belonging to logical
+ * eraseblock @lnum of volume @vol to a new physical eraseblock. Returns zero
+ * in case of success and a negative error code in case of failure.
+ * In case of error, it is possible that something was still written to the
+ * flash media, but may be some garbage.
+ */
+static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
+ struct ubi_vid_hdr *vid_hdr, const void *buf,
+ int offset, int len)
+{
+ struct ubi_device *ubi = vol->ubi;
+ int pnum, opnum, err, vol_id = vol->vol_id;
+
+ pnum = ubi_wl_get_peb(ubi);
+ if (pnum < 0) {
+ err = pnum;
+ goto out_put;
+ }
+
+ opnum = vol->eba_tbl[lnum];
+
+ dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d",
+ len, offset, vol_id, lnum, pnum);
+
+ err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
+ if (err) {
+ ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
+ vol_id, lnum, pnum);
+ goto out_put;
+ }
+
+ if (len) {
+ err = ubi_io_write_data(ubi, buf, pnum, offset, len);
+ 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);
+ goto out_put;
+ }
+ }
+
+ vol->eba_tbl[lnum] = pnum;
+
+out_put:
+ if (err && pnum >= 0)
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
+ else if (!err && opnum >= 0)
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0);
+
+ return err;
+}
+
+/**
* ubi_eba_write_leb - write data to dynamic volume.
* @ubi: UBI device description object
* @vol: volume description object
@@ -612,11 +673,12 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
* @vol. Returns zero in case of success and a negative error code in case
* of failure. In case of error, it is possible that something was still
* written to the flash media, but may be some garbage.
+ * This function retries %UBI_IO_RETRIES times before giving up.
*/
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
const void *buf, int offset, int len)
{
- int err, pnum, tries = 0, vol_id = vol->vol_id;
+ int err, pnum, tries, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
if (ubi->ro_mode)
@@ -637,11 +699,9 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
if (err == -EIO && ubi->bad_allowed)
err = recover_peb(ubi, pnum, vol_id, lnum, buf,
offset, len);
- if (err)
- ubi_ro_mode(ubi);
}
- leb_write_unlock(ubi, vol_id, lnum);
- return err;
+
+ goto out;
}
/*
@@ -661,63 +721,31 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
vid_hdr->compat = ubi_get_compat(ubi, vol_id);
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
-retry:
- pnum = ubi_wl_get_peb(ubi);
- if (pnum < 0) {
- ubi_free_vid_hdr(ubi, vid_hdr);
- leb_write_unlock(ubi, vol_id, lnum);
- return pnum;
- }
-
- dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d",
- len, offset, vol_id, lnum, pnum);
-
- err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
- if (err) {
- ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
- vol_id, lnum, pnum);
- goto write_error;
- }
+ for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
+ err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, offset,
+ len);
+ if (err != -EIO || !ubi->bad_allowed)
+ break;
- if (len) {
- err = ubi_io_write_data(ubi, buf, pnum, offset, len);
- 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);
- goto write_error;
- }
+ /*
+ * Fortunately, this is the first write operation to this
+ * physical eraseblock, so just put it and request a new one.
+ * We assume that if this physical eraseblock went bad, the
+ * erase code will handle that.
+ */
+ vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+ ubi_msg(ubi, "try another PEB");
}
- vol->eba_tbl[lnum] = pnum;
-
- leb_write_unlock(ubi, vol_id, lnum);
ubi_free_vid_hdr(ubi, vid_hdr);
- return 0;
-write_error:
- if (err != -EIO || !ubi->bad_allowed) {
+out:
+ if (err)
ubi_ro_mode(ubi);
- leb_write_unlock(ubi, vol_id, lnum);
- ubi_free_vid_hdr(ubi, vid_hdr);
- return err;
- }
- /*
- * Fortunately, this is the first write operation to this physical
- * eraseblock, so just put it and request a new one. We assume that if
- * this physical eraseblock went bad, the erase code will handle that.
- */
- err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
- if (err || ++tries > UBI_IO_RETRIES) {
- ubi_ro_mode(ubi);
- leb_write_unlock(ubi, vol_id, lnum);
- ubi_free_vid_hdr(ubi, vid_hdr);
- return err;
- }
+ leb_write_unlock(ubi, vol_id, lnum);
- vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
- ubi_msg(ubi, "try another PEB");
- goto retry;
+ return err;
}
/**
@@ -745,7 +773,7 @@ write_error:
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len, int used_ebs)
{
- int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;
+ int err, tries, data_size = len, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;
@@ -763,10 +791,8 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
return -ENOMEM;
err = leb_write_lock(ubi, vol_id, lnum);
- if (err) {
- ubi_free_vid_hdr(ubi, vid_hdr);
- return err;
- }
+ if (err)
+ goto out;
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
vid_hdr->vol_id = cpu_to_be32(vol_id);
@@ -780,62 +806,26 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
vid_hdr->used_ebs = cpu_to_be32(used_ebs);
vid_hdr->data_crc = cpu_to_be32(crc);
-retry:
- pnum = ubi_wl_get_peb(ubi);
- if (pnum < 0) {
- ubi_free_vid_hdr(ubi, vid_hdr);
- leb_write_unlock(ubi, vol_id, lnum);
- return pnum;
- }
-
- dbg_eba("write VID hdr and %d bytes at LEB %d:%d, PEB %d, used_ebs %d",
- len, vol_id, lnum, pnum, used_ebs);
+ ubi_assert(vol->eba_tbl[lnum] < 0);
- err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
- if (err) {
- ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
- vol_id, lnum, pnum);
- goto write_error;
- }
+ for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
+ err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len);
+ if (err != -EIO || !ubi->bad_allowed)
+ break;
- err = ubi_io_write_data(ubi, buf, pnum, 0, len);
- if (err) {
- ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
- len, pnum);
- goto write_error;
+ vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+ ubi_msg(ubi, "try another PEB");
}
- ubi_assert(vol->eba_tbl[lnum] < 0);
- vol->eba_tbl[lnum] = pnum;
+ if (err)
+ ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
- ubi_free_vid_hdr(ubi, vid_hdr);
- return 0;
-
-write_error:
- if (err != -EIO || !ubi->bad_allowed) {
- /*
- * This flash device does not admit of bad eraseblocks or
- * something nasty and unexpected happened. Switch to read-only
- * mode just in case.
- */
- ubi_ro_mode(ubi);
- leb_write_unlock(ubi, vol_id, lnum);
- ubi_free_vid_hdr(ubi, vid_hdr);
- return err;
- }
- err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
- if (err || ++tries > UBI_IO_RETRIES) {
- ubi_ro_mode(ubi);
- leb_write_unlock(ubi, vol_id, lnum);
- ubi_free_vid_hdr(ubi, vid_hdr);
- return err;
- }
+out:
+ ubi_free_vid_hdr(ubi, vid_hdr);
- vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
- ubi_msg(ubi, "try another PEB");
- goto retry;
+ return err;
}
/*
@@ -858,7 +848,7 @@ write_error:
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
int lnum, const void *buf, int len)
{
- int err, pnum, old_pnum, tries = 0, vol_id = vol->vol_id;
+ int err, tries, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;
@@ -896,65 +886,30 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
vid_hdr->copy_flag = 1;
vid_hdr->data_crc = cpu_to_be32(crc);
-retry:
- pnum = ubi_wl_get_peb(ubi);
- if (pnum < 0) {
- err = pnum;
- goto out_leb_unlock;
- }
-
- dbg_eba("change LEB %d:%d, PEB %d, write VID hdr to PEB %d",
- vol_id, lnum, vol->eba_tbl[lnum], pnum);
+ dbg_eba("change LEB %d:%d", vol_id, lnum);
- err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
- if (err) {
- ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
- vol_id, lnum, pnum);
- goto write_error;
- }
+ for (tries = 0; tries <= UBI_IO_RETRIES; tries++) {
+ err = try_write_vid_and_data(vol, lnum, vid_hdr, buf, 0, len);
+ if (err != -EIO || !ubi->bad_allowed)
+ break;
- err = ubi_io_write_data(ubi, buf, pnum, 0, len);
- if (err) {
- ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
- len, pnum);
- goto write_error;
+ vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+ ubi_msg(ubi, "try another PEB");
}
- old_pnum = vol->eba_tbl[lnum];
- vol->eba_tbl[lnum] = pnum;
-
- if (old_pnum >= 0) {
- err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0);
- if (err)
- goto out_leb_unlock;
- }
+ /*
+ * This flash device does not admit of bad eraseblocks or
+ * something nasty and unexpected happened. Switch to read-only
+ * mode just in case.
+ */
+ if (err)
+ ubi_ro_mode(ubi);
-out_leb_unlock:
leb_write_unlock(ubi, vol_id, lnum);
+
out_mutex:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
-
-write_error:
- if (err != -EIO || !ubi->bad_allowed) {
- /*
- * This flash device does not admit of bad eraseblocks or
- * something nasty and unexpected happened. Switch to read-only
- * mode just in case.
- */
- ubi_ro_mode(ubi);
- goto out_leb_unlock;
- }
-
- err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
- if (err || ++tries > UBI_IO_RETRIES) {
- ubi_ro_mode(ubi);
- goto out_leb_unlock;
- }
-
- vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
- ubi_msg(ubi, "try another PEB");
- goto retry;
}
/**
--
2.7.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2018-08-29 12:20 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-29 12:19 [PATCH 00/56] Update Barebox UBI Teresa Remmet
2018-08-29 12:19 ` [PATCH 01/56] UBI: Fastmap: Fix memory leak while attaching Teresa Remmet
2018-08-29 12:19 ` [PATCH 02/56] UBI: Remove alloc_ai() slab name from parameter list Teresa Remmet
2018-08-29 12:19 ` [PATCH 03/56] UBI: Don't read back all data in ubi_eba_copy_leb() Teresa Remmet
2018-08-29 12:19 ` [PATCH 04/56] UBI: Modify wrong comment in ubi_leb_map function Teresa Remmet
2018-08-29 12:19 ` [PATCH 05/56] UBI: Clean up return in ubi_remove_volume() Teresa Remmet
2018-08-29 12:19 ` [PATCH 06/56] UBI: Set free_count to zero before walking through erase list Teresa Remmet
2018-08-29 12:19 ` [PATCH 07/56] UBI: Fix static volume checks when Fastmap is used Teresa Remmet
2018-08-29 12:19 ` [PATCH 08/56] ubi: Make recover_peb power cut aware Teresa Remmet
2018-08-29 12:19 ` [PATCH 09/56] ubi: Fix race condition between ubi device creation and udev Teresa Remmet
2018-08-29 12:19 ` [PATCH 10/56] ubi: Fix early logging Teresa Remmet
2018-08-29 12:19 ` [PATCH 11/56] ubi: Make volume resize power cut aware Teresa Remmet
2018-08-29 12:19 ` [PATCH 12/56] ubi: Fix scan_fast() comment Teresa Remmet
2018-08-29 12:19 ` [PATCH 13/56] ubi: Introduce vol_ignored() Teresa Remmet
2018-08-29 12:19 ` [PATCH 14/56] ubi: Fix whitespace issue in count_fastmap_pebs() Teresa Remmet
2018-08-29 12:19 ` [PATCH 15/56] ubi: Rework Fastmap attach base code Teresa Remmet
2018-08-29 12:19 ` [PATCH 16/56] ubi: Check whether the Fastmap anchor matches the super block Teresa Remmet
2018-08-29 12:19 ` [PATCH 17/56] ubi: Be more paranoid while seaching for the most recent Fastmap Teresa Remmet
2018-08-29 12:19 ` [PATCH 18/56] UBI: fastmap: use ubi_find_volume() instead of open coding it Teresa Remmet
2018-08-29 12:19 ` [PATCH 19/56] UBI: fix add_fastmap() to use the vid_hdr passed in argument Teresa Remmet
2018-08-29 12:19 ` [PATCH 20/56] UBI: fastmap: avoid multiple be32_to_cpu() when unneccesary Teresa Remmet
2018-08-29 12:19 ` [PATCH 21/56] UBI: fastmap: scrub PEB when bitflips are detected in a free PEB EC header Teresa Remmet
2018-08-29 12:19 ` [PATCH 22/56] UBI: factorize code used to manipulate volumes at attach time Teresa Remmet
2018-08-29 12:19 ` [PATCH 23/56] UBI: factorize destroy_av() and ubi_remove_av() code Teresa Remmet
2018-08-29 12:19 ` [PATCH 24/56] UBI: fastmap: use ubi_rb_for_each_entry() in unmap_peb() Teresa Remmet
2018-08-29 12:19 ` [PATCH 25/56] UBI: fastmap: use ubi_io_{read, write}_data() instead of ubi_io_{read, write}() Teresa Remmet
2018-08-29 12:19 ` [PATCH 26/56] UBI: provide helpers to allocate and free aeb elements Teresa Remmet
2018-08-29 12:19 ` [PATCH 27/56] UBI: move the global ech and vidh variables into struct ubi_attach_info Teresa Remmet
2018-08-29 12:19 ` [PATCH 28/56] UBI: simplify recover_peb() code Teresa Remmet
2018-08-29 12:19 ` Teresa Remmet [this message]
2018-08-29 12:19 ` [PATCH 30/56] UBI: add an helper to check lnum validity Teresa Remmet
2018-08-29 12:19 ` [PATCH 31/56] UBI: provide an helper to check whether a LEB is mapped or not Teresa Remmet
2018-08-29 12:19 ` [PATCH 32/56] UBI: provide an helper to query LEB information Teresa Remmet
2018-08-29 12:19 ` [PATCH 33/56] UBI: hide EBA internals Teresa Remmet
2018-08-29 12:19 ` [PATCH 34/56] UBI: introduce the VID buffer concept Teresa Remmet
2018-08-29 12:19 ` [PATCH 35/56] ubi: Deal with interrupted erasures in WL Teresa Remmet
2018-08-29 12:19 ` [PATCH 36/56] ubi: Fix races around ubi_refill_pools() Teresa Remmet
2018-08-29 12:19 ` [PATCH 37/56] ubi: Fix Fastmap's update_vol() Teresa Remmet
2018-08-29 12:19 ` [PATCH 38/56] ubi: fix swapped arguments to call to ubi_alloc_aeb Teresa Remmet
2018-08-29 12:19 ` [PATCH 39/56] UBI: Fix crash in try_recover_peb() Teresa Remmet
2018-08-29 12:19 ` [PATCH 40/56] ubi: fastmap: Fix add_vol() return value test in ubi_attach_fastmap() Teresa Remmet
2018-08-29 12:19 ` [PATCH 41/56] UBI: Fix typos Teresa Remmet
2018-08-29 12:19 ` [PATCH 42/56] ubi/upd: Always flush after prepared for an update Teresa Remmet
2018-08-29 12:19 ` [PATCH 43/56] ubi: fastmap: Fix slab corruption Teresa Remmet
2018-08-29 12:20 ` [PATCH 44/56] ubi: pr_err() strings should end with newlines Teresa Remmet
2018-08-29 12:20 ` [PATCH 45/56] ubi: fastmap: fix spelling mistake: "invalidiate" -> "invalidate" Teresa Remmet
2018-08-29 12:20 ` [PATCH 46/56] UBI: Fix two typos in comments Teresa Remmet
2018-08-29 12:20 ` [PATCH 47/56] ubi: fastmap: Clean up the initialization of pointer p Teresa Remmet
2018-08-29 12:20 ` [PATCH 48/56] ubi: fastmap: Erase outdated anchor PEBs during attach Teresa Remmet
2018-08-29 12:20 ` [PATCH 49/56] ubi: Fastmap: Fix typo Teresa Remmet
2018-08-29 12:20 ` [PATCH 50/56] ubi: Fix copy/paste error in function documentation Teresa Remmet
2018-08-29 12:20 ` [PATCH 51/56] mtd: ubi: wl: Fix error return code in ubi_wl_init() Teresa Remmet
2018-08-29 12:20 ` [PATCH 52/56] ubi: fastmap: Correctly handle interrupted erasures in EBA Teresa Remmet
2018-08-29 12:20 ` [PATCH 53/56] ubi: fastmap: Check each mapping only once Teresa Remmet
2018-08-29 12:20 ` [PATCH 54/56] ubi: fastmap: Detect EBA mismatches on-the-fly Teresa Remmet
2018-08-29 12:20 ` [PATCH 55/56] mtd: ubi: Update ubi-media.h to dual license Teresa Remmet
2018-08-29 12:20 ` [PATCH 56/56] ubi: Initialize Fastmap checkmapping correctly Teresa Remmet
2018-08-31 6:25 ` [PATCH 00/56] Update Barebox UBI Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1535545212-18871-30-git-send-email-t.remmet@phytec.de \
--to=t.remmet@phytec.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox