diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-26 22:55:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-26 22:55:16 -0500 |
commit | 3bef22eed98b53cfb3962884f14068251a5dd3f0 (patch) | |
tree | 7602b9239d5aa301cf8fcb37affafe86cb2bb832 | |
parent | e2b0a1613200a044b0e5e3a78d157ab746a7a4fa (diff) | |
parent | 6b238de189f69dc77d660d4cce62eed15547f4c3 (diff) |
Merge tag 'upstream-4.4-rc7' of git://git.infradead.org/linux-ubifs
Pull UBI bug fixes from Richard Weinberger:
"This contains four bug fixes for UBI"
* tag 'upstream-4.4-rc7' of git://git.infradead.org/linux-ubifs:
mtd: ubi: don't leak e if schedule_erase() fails
mtd: ubi: fixup error correction in do_sync_erase()
UBI: fix use of "VID" vs. "EC" in header self-check
UBI: fix return error code
-rw-r--r-- | drivers/mtd/ubi/debug.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 53 |
3 files changed, 31 insertions, 26 deletions
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index b077e43b5ba9..c4cb15a3098c 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
@@ -236,7 +236,7 @@ int ubi_debugfs_init(void) | |||
236 | 236 | ||
237 | dfs_rootdir = debugfs_create_dir("ubi", NULL); | 237 | dfs_rootdir = debugfs_create_dir("ubi", NULL); |
238 | if (IS_ERR_OR_NULL(dfs_rootdir)) { | 238 | if (IS_ERR_OR_NULL(dfs_rootdir)) { |
239 | int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir); | 239 | int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV; |
240 | 240 | ||
241 | pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n", | 241 | pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n", |
242 | err); | 242 | err); |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 1fc23e48fe8e..10cf3b549959 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -1299,7 +1299,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) | |||
1299 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) | 1299 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) |
1300 | goto exit; | 1300 | goto exit; |
1301 | 1301 | ||
1302 | crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC); | 1302 | crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); |
1303 | hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); | 1303 | hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); |
1304 | if (hdr_crc != crc) { | 1304 | if (hdr_crc != crc) { |
1305 | ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x", | 1305 | ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x", |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index eb4489f9082f..56065632a5b8 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -603,6 +603,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, | |||
603 | return 0; | 603 | return 0; |
604 | } | 604 | } |
605 | 605 | ||
606 | static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk); | ||
606 | /** | 607 | /** |
607 | * do_sync_erase - run the erase worker synchronously. | 608 | * do_sync_erase - run the erase worker synchronously. |
608 | * @ubi: UBI device description object | 609 | * @ubi: UBI device description object |
@@ -615,20 +616,16 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, | |||
615 | static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, | 616 | static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, |
616 | int vol_id, int lnum, int torture) | 617 | int vol_id, int lnum, int torture) |
617 | { | 618 | { |
618 | struct ubi_work *wl_wrk; | 619 | struct ubi_work wl_wrk; |
619 | 620 | ||
620 | dbg_wl("sync erase of PEB %i", e->pnum); | 621 | dbg_wl("sync erase of PEB %i", e->pnum); |
621 | 622 | ||
622 | wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS); | 623 | wl_wrk.e = e; |
623 | if (!wl_wrk) | 624 | wl_wrk.vol_id = vol_id; |
624 | return -ENOMEM; | 625 | wl_wrk.lnum = lnum; |
625 | 626 | wl_wrk.torture = torture; | |
626 | wl_wrk->e = e; | ||
627 | wl_wrk->vol_id = vol_id; | ||
628 | wl_wrk->lnum = lnum; | ||
629 | wl_wrk->torture = torture; | ||
630 | 627 | ||
631 | return erase_worker(ubi, wl_wrk, 0); | 628 | return __erase_worker(ubi, &wl_wrk); |
632 | } | 629 | } |
633 | 630 | ||
634 | /** | 631 | /** |
@@ -1014,7 +1011,7 @@ out_unlock: | |||
1014 | } | 1011 | } |
1015 | 1012 | ||
1016 | /** | 1013 | /** |
1017 | * erase_worker - physical eraseblock erase worker function. | 1014 | * __erase_worker - physical eraseblock erase worker function. |
1018 | * @ubi: UBI device description object | 1015 | * @ubi: UBI device description object |
1019 | * @wl_wrk: the work object | 1016 | * @wl_wrk: the work object |
1020 | * @shutdown: non-zero if the worker has to free memory and exit | 1017 | * @shutdown: non-zero if the worker has to free memory and exit |
@@ -1025,8 +1022,7 @@ out_unlock: | |||
1025 | * needed. Returns zero in case of success and a negative error code in case of | 1022 | * needed. Returns zero in case of success and a negative error code in case of |
1026 | * failure. | 1023 | * failure. |
1027 | */ | 1024 | */ |
1028 | static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | 1025 | static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) |
1029 | int shutdown) | ||
1030 | { | 1026 | { |
1031 | struct ubi_wl_entry *e = wl_wrk->e; | 1027 | struct ubi_wl_entry *e = wl_wrk->e; |
1032 | int pnum = e->pnum; | 1028 | int pnum = e->pnum; |
@@ -1034,21 +1030,11 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
1034 | int lnum = wl_wrk->lnum; | 1030 | int lnum = wl_wrk->lnum; |
1035 | int err, available_consumed = 0; | 1031 | int err, available_consumed = 0; |
1036 | 1032 | ||
1037 | if (shutdown) { | ||
1038 | dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); | ||
1039 | kfree(wl_wrk); | ||
1040 | wl_entry_destroy(ubi, e); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | dbg_wl("erase PEB %d EC %d LEB %d:%d", | 1033 | dbg_wl("erase PEB %d EC %d LEB %d:%d", |
1045 | pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); | 1034 | pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); |
1046 | 1035 | ||
1047 | err = sync_erase(ubi, e, wl_wrk->torture); | 1036 | err = sync_erase(ubi, e, wl_wrk->torture); |
1048 | if (!err) { | 1037 | if (!err) { |
1049 | /* Fine, we've erased it successfully */ | ||
1050 | kfree(wl_wrk); | ||
1051 | |||
1052 | spin_lock(&ubi->wl_lock); | 1038 | spin_lock(&ubi->wl_lock); |
1053 | wl_tree_add(e, &ubi->free); | 1039 | wl_tree_add(e, &ubi->free); |
1054 | ubi->free_count++; | 1040 | ubi->free_count++; |
@@ -1066,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
1066 | } | 1052 | } |
1067 | 1053 | ||
1068 | ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err); | 1054 | ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err); |
1069 | kfree(wl_wrk); | ||
1070 | 1055 | ||
1071 | if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || | 1056 | if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || |
1072 | err == -EBUSY) { | 1057 | err == -EBUSY) { |
@@ -1075,6 +1060,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
1075 | /* Re-schedule the LEB for erasure */ | 1060 | /* Re-schedule the LEB for erasure */ |
1076 | err1 = schedule_erase(ubi, e, vol_id, lnum, 0); | 1061 | err1 = schedule_erase(ubi, e, vol_id, lnum, 0); |
1077 | if (err1) { | 1062 | if (err1) { |
1063 | wl_entry_destroy(ubi, e); | ||
1078 | err = err1; | 1064 | err = err1; |
1079 | goto out_ro; | 1065 | goto out_ro; |
1080 | } | 1066 | } |
@@ -1150,6 +1136,25 @@ out_ro: | |||
1150 | return err; | 1136 | return err; |
1151 | } | 1137 | } |
1152 | 1138 | ||
1139 | static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | ||
1140 | int shutdown) | ||
1141 | { | ||
1142 | int ret; | ||
1143 | |||
1144 | if (shutdown) { | ||
1145 | struct ubi_wl_entry *e = wl_wrk->e; | ||
1146 | |||
1147 | dbg_wl("cancel erasure of PEB %d EC %d", e->pnum, e->ec); | ||
1148 | kfree(wl_wrk); | ||
1149 | wl_entry_destroy(ubi, e); | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | ret = __erase_worker(ubi, wl_wrk); | ||
1154 | kfree(wl_wrk); | ||
1155 | return ret; | ||
1156 | } | ||
1157 | |||
1153 | /** | 1158 | /** |
1154 | * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. | 1159 | * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. |
1155 | * @ubi: UBI device description object | 1160 | * @ubi: UBI device description object |