Skip to content

Commit 784c145

Browse files
Artem BityutskiyArtem Bityutskiy
authored andcommitted
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: Vinit Agnihotri <[email protected]> Signed-off-by: Artem Bityutskiy <[email protected]>
1 parent 63b6c1e commit 784c145

File tree

1 file changed

+48
-41
lines changed

1 file changed

+48
-41
lines changed

drivers/mtd/ubi/wl.c

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,9 +1060,8 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
10601060
static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
10611061
int cancel)
10621062
{
1063-
int err;
10641063
struct ubi_wl_entry *e = wl_wrk->e;
1065-
int pnum = e->pnum;
1064+
int pnum = e->pnum, err, need;
10661065

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

1100-
if (err != -EIO) {
1099+
if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
1100+
err == -EBUSY) {
1101+
int err1;
1102+
1103+
/* Re-schedule the LEB for erasure */
1104+
err1 = schedule_erase(ubi, e, 0);
1105+
if (err1) {
1106+
err = err1;
1107+
goto out_ro;
1108+
}
1109+
return err;
1110+
} else if (err != -EIO) {
11011111
/*
11021112
* If this is not %-EIO, we have no idea what to do. Scheduling
11031113
* this physical eraseblock for erasure again would cause
11041114
* errors again and again. Well, lets switch to RO mode.
11051115
*/
1106-
ubi_ro_mode(ubi);
1107-
return err;
1116+
goto out_ro;
11081117
}
11091118

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

11121121
if (!ubi->bad_allowed) {
11131122
ubi_err("bad physical eraseblock %d detected", pnum);
1114-
ubi_ro_mode(ubi);
1115-
err = -EIO;
1116-
} else {
1117-
int need;
1118-
1119-
spin_lock(&ubi->volumes_lock);
1120-
need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
1121-
if (need > 0) {
1122-
need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
1123-
ubi->avail_pebs -= need;
1124-
ubi->rsvd_pebs += need;
1125-
ubi->beb_rsvd_pebs += need;
1126-
if (need > 0)
1127-
ubi_msg("reserve more %d PEBs", need);
1128-
}
1123+
goto out_ro;
1124+
}
11291125

1130-
if (ubi->beb_rsvd_pebs == 0) {
1131-
spin_unlock(&ubi->volumes_lock);
1132-
ubi_err("no reserved physical eraseblocks");
1133-
ubi_ro_mode(ubi);
1134-
return -EIO;
1135-
}
1126+
spin_lock(&ubi->volumes_lock);
1127+
need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
1128+
if (need > 0) {
1129+
need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
1130+
ubi->avail_pebs -= need;
1131+
ubi->rsvd_pebs += need;
1132+
ubi->beb_rsvd_pebs += need;
1133+
if (need > 0)
1134+
ubi_msg("reserve more %d PEBs", need);
1135+
}
11361136

1137+
if (ubi->beb_rsvd_pebs == 0) {
11371138
spin_unlock(&ubi->volumes_lock);
1138-
ubi_msg("mark PEB %d as bad", pnum);
1139+
ubi_err("no reserved physical eraseblocks");
1140+
goto out_ro;
1141+
}
11391142

1140-
err = ubi_io_mark_bad(ubi, pnum);
1141-
if (err) {
1142-
ubi_ro_mode(ubi);
1143-
return err;
1144-
}
1143+
spin_unlock(&ubi->volumes_lock);
1144+
ubi_msg("mark PEB %d as bad", pnum);
11451145

1146-
spin_lock(&ubi->volumes_lock);
1147-
ubi->beb_rsvd_pebs -= 1;
1148-
ubi->bad_peb_count += 1;
1149-
ubi->good_peb_count -= 1;
1150-
ubi_calculate_reserved(ubi);
1151-
if (ubi->beb_rsvd_pebs == 0)
1152-
ubi_warn("last PEB from the reserved pool was used");
1153-
spin_unlock(&ubi->volumes_lock);
1154-
}
1146+
err = ubi_io_mark_bad(ubi, pnum);
1147+
if (err)
1148+
goto out_ro;
1149+
1150+
spin_lock(&ubi->volumes_lock);
1151+
ubi->beb_rsvd_pebs -= 1;
1152+
ubi->bad_peb_count += 1;
1153+
ubi->good_peb_count -= 1;
1154+
ubi_calculate_reserved(ubi);
1155+
if (ubi->beb_rsvd_pebs == 0)
1156+
ubi_warn("last PEB from the reserved pool was used");
1157+
spin_unlock(&ubi->volumes_lock);
1158+
1159+
return err;
11551160

1161+
out_ro:
1162+
ubi_ro_mode(ubi);
11561163
return err;
11571164
}
11581165

0 commit comments

Comments
 (0)