diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 17:57:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 17:57:19 -0500 |
commit | 5c395ae7033099fc657114ea997858aa622f08b2 (patch) | |
tree | f714c8d8db528274de2da4f8aa64b69af0d2aa5e /drivers/mtd | |
parent | 49d41bae46f15da528ef9848fd7c9d38582aa8e9 (diff) | |
parent | e57e0d8e818512047fe379157c3f77f1b9fabffb (diff) |
Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
* 'linux-next' of git://git.infradead.org/ubifs-2.6:
UBI: fix use-after-free on error path
UBI: fix missing scrub when there is a bit-flip
UBIFS: Use kmemdup rather than duplicating its implementation
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 12 |
3 files changed, 14 insertions, 6 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index fb7f19b62d91..cd26da8ad225 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -1028,12 +1028,14 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1028 | * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are | 1028 | * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are |
1029 | * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the | 1029 | * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the |
1030 | * LEB is already locked, we just do not move it and return | 1030 | * LEB is already locked, we just do not move it and return |
1031 | * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later. | 1031 | * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because |
1032 | * we do not know the reasons of the contention - it may be just a | ||
1033 | * normal I/O on this LEB, so we want to re-try. | ||
1032 | */ | 1034 | */ |
1033 | err = leb_write_trylock(ubi, vol_id, lnum); | 1035 | err = leb_write_trylock(ubi, vol_id, lnum); |
1034 | if (err) { | 1036 | if (err) { |
1035 | dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum); | 1037 | dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum); |
1036 | return MOVE_CANCEL_RACE; | 1038 | return MOVE_RETRY; |
1037 | } | 1039 | } |
1038 | 1040 | ||
1039 | /* | 1041 | /* |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index dc64c767fd21..d51d75d34446 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -120,6 +120,7 @@ enum { | |||
120 | * PEB | 120 | * PEB |
121 | * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the | 121 | * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the |
122 | * target PEB | 122 | * target PEB |
123 | * MOVE_RETRY: retry scrubbing the PEB | ||
123 | */ | 124 | */ |
124 | enum { | 125 | enum { |
125 | MOVE_CANCEL_RACE = 1, | 126 | MOVE_CANCEL_RACE = 1, |
@@ -127,6 +128,7 @@ enum { | |||
127 | MOVE_TARGET_RD_ERR, | 128 | MOVE_TARGET_RD_ERR, |
128 | MOVE_TARGET_WR_ERR, | 129 | MOVE_TARGET_WR_ERR, |
129 | MOVE_CANCEL_BITFLIPS, | 130 | MOVE_CANCEL_BITFLIPS, |
131 | MOVE_RETRY, | ||
130 | }; | 132 | }; |
131 | 133 | ||
132 | /** | 134 | /** |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 42c684cf3688..0696e36b0539 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -795,7 +795,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | |||
795 | protect = 1; | 795 | protect = 1; |
796 | goto out_not_moved; | 796 | goto out_not_moved; |
797 | } | 797 | } |
798 | 798 | if (err == MOVE_RETRY) { | |
799 | scrubbing = 1; | ||
800 | goto out_not_moved; | ||
801 | } | ||
799 | if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR || | 802 | if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR || |
800 | err == MOVE_TARGET_RD_ERR) { | 803 | err == MOVE_TARGET_RD_ERR) { |
801 | /* | 804 | /* |
@@ -1049,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
1049 | 1052 | ||
1050 | ubi_err("failed to erase PEB %d, error %d", pnum, err); | 1053 | ubi_err("failed to erase PEB %d, error %d", pnum, err); |
1051 | kfree(wl_wrk); | 1054 | kfree(wl_wrk); |
1052 | kmem_cache_free(ubi_wl_entry_slab, e); | ||
1053 | 1055 | ||
1054 | if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || | 1056 | if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || |
1055 | err == -EBUSY) { | 1057 | err == -EBUSY) { |
@@ -1062,14 +1064,16 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
1062 | goto out_ro; | 1064 | goto out_ro; |
1063 | } | 1065 | } |
1064 | return err; | 1066 | return err; |
1065 | } else if (err != -EIO) { | 1067 | } |
1068 | |||
1069 | kmem_cache_free(ubi_wl_entry_slab, e); | ||
1070 | if (err != -EIO) | ||
1066 | /* | 1071 | /* |
1067 | * If this is not %-EIO, we have no idea what to do. Scheduling | 1072 | * If this is not %-EIO, we have no idea what to do. Scheduling |
1068 | * this physical eraseblock for erasure again would cause | 1073 | * this physical eraseblock for erasure again would cause |
1069 | * errors again and again. Well, lets switch to R/O mode. | 1074 | * errors again and again. Well, lets switch to R/O mode. |
1070 | */ | 1075 | */ |
1071 | goto out_ro; | 1076 | goto out_ro; |
1072 | } | ||
1073 | 1077 | ||
1074 | /* It is %-EIO, the PEB went bad */ | 1078 | /* It is %-EIO, the PEB went bad */ |
1075 | 1079 | ||