Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 784c1454 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBI: fix error handling in erase worker



Do not switch to read-only mode in case of -EINTR and some
other obvious cases. Switch to RO mode only when we do not
know what is the error.

Reported-by: default avatarVinit Agnihotri <vinit.agnihotri@gmail.com>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 63b6c1ed
Loading
Loading
Loading
Loading
+48 −41
Original line number Diff line number Diff line
@@ -1060,9 +1060,8 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
			int cancel)
{
	int err;
	struct ubi_wl_entry *e = wl_wrk->e;
	int pnum = e->pnum;
	int pnum = e->pnum, err, need;

	if (cancel) {
		dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1097,24 +1096,32 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	kfree(wl_wrk);
	kmem_cache_free(wl_entries_slab, e);

	if (err != -EIO) {
	if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
	    err == -EBUSY) {
		int err1;

		/* Re-schedule the LEB for erasure */
		err1 = schedule_erase(ubi, e, 0);
		if (err1) {
			err = err1;
			goto out_ro;
		}
		return err;
	} else if (err != -EIO) {
		/*
		 * If this is not %-EIO, we have no idea what to do. Scheduling
		 * this physical eraseblock for erasure again would cause
		 * errors again and again. Well, lets switch to RO mode.
		 */
		ubi_ro_mode(ubi);
		return err;
		goto out_ro;
	}

	/* It is %-EIO, the PEB went bad */

	if (!ubi->bad_allowed) {
		ubi_err("bad physical eraseblock %d detected", pnum);
		ubi_ro_mode(ubi);
		err = -EIO;
	} else {
		int need;
		goto out_ro;
	}

	spin_lock(&ubi->volumes_lock);
	need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
@@ -1130,18 +1137,15 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	if (ubi->beb_rsvd_pebs == 0) {
		spin_unlock(&ubi->volumes_lock);
		ubi_err("no reserved physical eraseblocks");
			ubi_ro_mode(ubi);
			return -EIO;
		goto out_ro;
	}

	spin_unlock(&ubi->volumes_lock);
	ubi_msg("mark PEB %d as bad", pnum);

	err = ubi_io_mark_bad(ubi, pnum);
		if (err) {
			ubi_ro_mode(ubi);
			return err;
		}
	if (err)
		goto out_ro;

	spin_lock(&ubi->volumes_lock);
	ubi->beb_rsvd_pebs -= 1;
@@ -1151,9 +1155,12 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
	if (ubi->beb_rsvd_pebs == 0)
		ubi_warn("last PEB from the reserved pool was used");
	spin_unlock(&ubi->volumes_lock);
	}

	return err;

out_ro:
	ubi_ro_mode(ubi);
	return err;
}

/**