diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-08-29 07:51:52 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-10-14 06:10:21 -0400 |
commit | e88d6e10e5c848fd5be8f89e09e3bce2570886b7 (patch) | |
tree | 27b5547a0e24add89deafedaed784328bc3c173e /drivers/mtd/ubi/io.c | |
parent | 33818bbb84cd371b63ed8849cc5264d24c8b3aa2 (diff) |
UBI: do not use vmalloc on I/O path
Similar reason as in case of the previous patch: it causes
deadlocks if a filesystem with writeback support works on top
of UBI. So pre-allocate needed buffers when attaching MTD device.
We also need mutexes to protect the buffers, but they do not
cause much contantion because they are used in recovery, torture,
and WL copy routines, which are called seldom.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/io.c')
-rw-r--r-- | drivers/mtd/ubi/io.c | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index ba5bc4a5379e..52476d884c48 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -98,8 +98,8 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); | 98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); |
99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, | 99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, |
100 | const struct ubi_vid_hdr *vid_hdr); | 100 | const struct ubi_vid_hdr *vid_hdr); |
101 | static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum, | 101 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, |
102 | int offset, int len); | 102 | int len); |
103 | #else | 103 | #else |
104 | #define paranoid_check_not_bad(ubi, pnum) 0 | 104 | #define paranoid_check_not_bad(ubi, pnum) 0 |
105 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 | 105 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 |
@@ -202,8 +202,8 @@ retry: | |||
202 | * Note, in case of an error, it is possible that something was still written | 202 | * Note, in case of an error, it is possible that something was still written |
203 | * to the flash media, but may be some garbage. | 203 | * to the flash media, but may be some garbage. |
204 | */ | 204 | */ |
205 | int ubi_io_write(const struct ubi_device *ubi, const void *buf, int pnum, | 205 | int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, |
206 | int offset, int len) | 206 | int len) |
207 | { | 207 | { |
208 | int err; | 208 | int err; |
209 | size_t written; | 209 | size_t written; |
@@ -285,7 +285,7 @@ static void erase_callback(struct erase_info *ei) | |||
285 | * zero in case of success and a negative error code in case of failure. If | 285 | * zero in case of success and a negative error code in case of failure. If |
286 | * %-EIO is returned, the physical eraseblock most probably went bad. | 286 | * %-EIO is returned, the physical eraseblock most probably went bad. |
287 | */ | 287 | */ |
288 | static int do_sync_erase(const struct ubi_device *ubi, int pnum) | 288 | static int do_sync_erase(struct ubi_device *ubi, int pnum) |
289 | { | 289 | { |
290 | int err, retries = 0; | 290 | int err, retries = 0; |
291 | struct erase_info ei; | 291 | struct erase_info ei; |
@@ -377,29 +377,25 @@ static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; | |||
377 | * test, a positive number of erase operations done if the test was | 377 | * test, a positive number of erase operations done if the test was |
378 | * successfully passed, and other negative error codes in case of other errors. | 378 | * successfully passed, and other negative error codes in case of other errors. |
379 | */ | 379 | */ |
380 | static int torture_peb(const struct ubi_device *ubi, int pnum) | 380 | static int torture_peb(struct ubi_device *ubi, int pnum) |
381 | { | 381 | { |
382 | void *buf; | ||
383 | int err, i, patt_count; | 382 | int err, i, patt_count; |
384 | 383 | ||
385 | buf = vmalloc(ubi->peb_size); | ||
386 | if (!buf) | ||
387 | return -ENOMEM; | ||
388 | |||
389 | patt_count = ARRAY_SIZE(patterns); | 384 | patt_count = ARRAY_SIZE(patterns); |
390 | ubi_assert(patt_count > 0); | 385 | ubi_assert(patt_count > 0); |
391 | 386 | ||
387 | mutex_lock(&ubi->buf_mutex); | ||
392 | for (i = 0; i < patt_count; i++) { | 388 | for (i = 0; i < patt_count; i++) { |
393 | err = do_sync_erase(ubi, pnum); | 389 | err = do_sync_erase(ubi, pnum); |
394 | if (err) | 390 | if (err) |
395 | goto out; | 391 | goto out; |
396 | 392 | ||
397 | /* Make sure the PEB contains only 0xFF bytes */ | 393 | /* Make sure the PEB contains only 0xFF bytes */ |
398 | err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size); | 394 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); |
399 | if (err) | 395 | if (err) |
400 | goto out; | 396 | goto out; |
401 | 397 | ||
402 | err = check_pattern(buf, 0xFF, ubi->peb_size); | 398 | err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size); |
403 | if (err == 0) { | 399 | if (err == 0) { |
404 | ubi_err("erased PEB %d, but a non-0xFF byte found", | 400 | ubi_err("erased PEB %d, but a non-0xFF byte found", |
405 | pnum); | 401 | pnum); |
@@ -408,17 +404,17 @@ static int torture_peb(const struct ubi_device *ubi, int pnum) | |||
408 | } | 404 | } |
409 | 405 | ||
410 | /* Write a pattern and check it */ | 406 | /* Write a pattern and check it */ |
411 | memset(buf, patterns[i], ubi->peb_size); | 407 | memset(ubi->peb_buf1, patterns[i], ubi->peb_size); |
412 | err = ubi_io_write(ubi, buf, pnum, 0, ubi->peb_size); | 408 | err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); |
413 | if (err) | 409 | if (err) |
414 | goto out; | 410 | goto out; |
415 | 411 | ||
416 | memset(buf, ~patterns[i], ubi->peb_size); | 412 | memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size); |
417 | err = ubi_io_read(ubi, buf, pnum, 0, ubi->peb_size); | 413 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size); |
418 | if (err) | 414 | if (err) |
419 | goto out; | 415 | goto out; |
420 | 416 | ||
421 | err = check_pattern(buf, patterns[i], ubi->peb_size); | 417 | err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size); |
422 | if (err == 0) { | 418 | if (err == 0) { |
423 | ubi_err("pattern %x checking failed for PEB %d", | 419 | ubi_err("pattern %x checking failed for PEB %d", |
424 | patterns[i], pnum); | 420 | patterns[i], pnum); |
@@ -430,6 +426,7 @@ static int torture_peb(const struct ubi_device *ubi, int pnum) | |||
430 | err = patt_count; | 426 | err = patt_count; |
431 | 427 | ||
432 | out: | 428 | out: |
429 | mutex_unlock(&ubi->buf_mutex); | ||
433 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) { | 430 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) { |
434 | /* | 431 | /* |
435 | * If a bit-flip or data integrity error was detected, the test | 432 | * If a bit-flip or data integrity error was detected, the test |
@@ -440,7 +437,6 @@ out: | |||
440 | pnum); | 437 | pnum); |
441 | err = -EIO; | 438 | err = -EIO; |
442 | } | 439 | } |
443 | vfree(buf); | ||
444 | return err; | 440 | return err; |
445 | } | 441 | } |
446 | 442 | ||
@@ -460,7 +456,7 @@ out: | |||
460 | * codes in case of other errors. Note, %-EIO means that the physical | 456 | * codes in case of other errors. Note, %-EIO means that the physical |
461 | * eraseblock is bad. | 457 | * eraseblock is bad. |
462 | */ | 458 | */ |
463 | int ubi_io_sync_erase(const struct ubi_device *ubi, int pnum, int torture) | 459 | int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) |
464 | { | 460 | { |
465 | int err, ret = 0; | 461 | int err, ret = 0; |
466 | 462 | ||
@@ -617,7 +613,7 @@ bad: | |||
617 | * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; | 613 | * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; |
618 | * o a negative error code in case of failure. | 614 | * o a negative error code in case of failure. |
619 | */ | 615 | */ |
620 | int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum, | 616 | int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, |
621 | struct ubi_ec_hdr *ec_hdr, int verbose) | 617 | struct ubi_ec_hdr *ec_hdr, int verbose) |
622 | { | 618 | { |
623 | int err, read_err = 0; | 619 | int err, read_err = 0; |
@@ -723,7 +719,7 @@ int ubi_io_read_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
723 | * case of failure. If %-EIO is returned, the physical eraseblock most probably | 719 | * case of failure. If %-EIO is returned, the physical eraseblock most probably |
724 | * went bad. | 720 | * went bad. |
725 | */ | 721 | */ |
726 | int ubi_io_write_ec_hdr(const struct ubi_device *ubi, int pnum, | 722 | int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, |
727 | struct ubi_ec_hdr *ec_hdr) | 723 | struct ubi_ec_hdr *ec_hdr) |
728 | { | 724 | { |
729 | int err; | 725 | int err; |
@@ -889,7 +885,7 @@ bad: | |||
889 | * header there); | 885 | * header there); |
890 | * o a negative error code in case of failure. | 886 | * o a negative error code in case of failure. |
891 | */ | 887 | */ |
892 | int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum, | 888 | int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, |
893 | struct ubi_vid_hdr *vid_hdr, int verbose) | 889 | struct ubi_vid_hdr *vid_hdr, int verbose) |
894 | { | 890 | { |
895 | int err, read_err = 0; | 891 | int err, read_err = 0; |
@@ -996,7 +992,7 @@ int ubi_io_read_vid_hdr(const struct ubi_device *ubi, int pnum, | |||
996 | * case of failure. If %-EIO is returned, the physical eraseblock probably went | 992 | * case of failure. If %-EIO is returned, the physical eraseblock probably went |
997 | * bad. | 993 | * bad. |
998 | */ | 994 | */ |
999 | int ubi_io_write_vid_hdr(const struct ubi_device *ubi, int pnum, | 995 | int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, |
1000 | struct ubi_vid_hdr *vid_hdr) | 996 | struct ubi_vid_hdr *vid_hdr) |
1001 | { | 997 | { |
1002 | int err; | 998 | int err; |
@@ -1219,44 +1215,40 @@ exit: | |||
1219 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error | 1215 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error |
1220 | * code if an error occurred. | 1216 | * code if an error occurred. |
1221 | */ | 1217 | */ |
1222 | static int paranoid_check_all_ff(const struct ubi_device *ubi, int pnum, | 1218 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, |
1223 | int offset, int len) | 1219 | int len) |
1224 | { | 1220 | { |
1225 | size_t read; | 1221 | size_t read; |
1226 | int err; | 1222 | int err; |
1227 | void *buf; | ||
1228 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; | 1223 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; |
1229 | 1224 | ||
1230 | buf = vmalloc(len); | 1225 | mutex_lock(&ubi->dbg_buf_mutex); |
1231 | if (!buf) | 1226 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); |
1232 | return -ENOMEM; | ||
1233 | memset(buf, 0, len); | ||
1234 | |||
1235 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); | ||
1236 | if (err && err != -EUCLEAN) { | 1227 | if (err && err != -EUCLEAN) { |
1237 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " | 1228 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " |
1238 | "read %zd bytes", err, len, pnum, offset, read); | 1229 | "read %zd bytes", err, len, pnum, offset, read); |
1239 | goto error; | 1230 | goto error; |
1240 | } | 1231 | } |
1241 | 1232 | ||
1242 | err = check_pattern(buf, 0xFF, len); | 1233 | err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); |
1243 | if (err == 0) { | 1234 | if (err == 0) { |
1244 | ubi_err("flash region at PEB %d:%d, length %d does not " | 1235 | ubi_err("flash region at PEB %d:%d, length %d does not " |
1245 | "contain all 0xFF bytes", pnum, offset, len); | 1236 | "contain all 0xFF bytes", pnum, offset, len); |
1246 | goto fail; | 1237 | goto fail; |
1247 | } | 1238 | } |
1239 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
1248 | 1240 | ||
1249 | vfree(buf); | ||
1250 | return 0; | 1241 | return 0; |
1251 | 1242 | ||
1252 | fail: | 1243 | fail: |
1253 | ubi_err("paranoid check failed for PEB %d", pnum); | 1244 | ubi_err("paranoid check failed for PEB %d", pnum); |
1254 | dbg_msg("hex dump of the %d-%d region", offset, offset + len); | 1245 | dbg_msg("hex dump of the %d-%d region", offset, offset + len); |
1255 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); | 1246 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, |
1247 | ubi->dbg_peb_buf, len, 1); | ||
1256 | err = 1; | 1248 | err = 1; |
1257 | error: | 1249 | error: |
1258 | ubi_dbg_dump_stack(); | 1250 | ubi_dbg_dump_stack(); |
1259 | vfree(buf); | 1251 | mutex_unlock(&ubi->dbg_buf_mutex); |
1260 | return err; | 1252 | return err; |
1261 | } | 1253 | } |
1262 | 1254 | ||