diff options
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 70 |
1 files changed, 24 insertions, 46 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 89193104c6c8..81bb6a33b555 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -495,16 +495,18 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, | |||
495 | int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; | 495 | int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; |
496 | struct ubi_volume *vol = ubi->volumes[idx]; | 496 | struct ubi_volume *vol = ubi->volumes[idx]; |
497 | struct ubi_vid_hdr *vid_hdr; | 497 | struct ubi_vid_hdr *vid_hdr; |
498 | unsigned char *new_buf; | ||
499 | 498 | ||
500 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 499 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
501 | if (!vid_hdr) { | 500 | if (!vid_hdr) { |
502 | return -ENOMEM; | 501 | return -ENOMEM; |
503 | } | 502 | } |
504 | 503 | ||
504 | mutex_lock(&ubi->buf_mutex); | ||
505 | |||
505 | retry: | 506 | retry: |
506 | new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); | 507 | new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); |
507 | if (new_pnum < 0) { | 508 | if (new_pnum < 0) { |
509 | mutex_unlock(&ubi->buf_mutex); | ||
508 | ubi_free_vid_hdr(ubi, vid_hdr); | 510 | ubi_free_vid_hdr(ubi, vid_hdr); |
509 | return new_pnum; | 511 | return new_pnum; |
510 | } | 512 | } |
@@ -524,31 +526,22 @@ retry: | |||
524 | goto write_error; | 526 | goto write_error; |
525 | 527 | ||
526 | data_size = offset + len; | 528 | data_size = offset + len; |
527 | new_buf = vmalloc(data_size); | 529 | memset(ubi->peb_buf1 + offset, 0xFF, len); |
528 | if (!new_buf) { | ||
529 | err = -ENOMEM; | ||
530 | goto out_put; | ||
531 | } | ||
532 | memset(new_buf + offset, 0xFF, len); | ||
533 | 530 | ||
534 | /* Read everything before the area where the write failure happened */ | 531 | /* Read everything before the area where the write failure happened */ |
535 | if (offset > 0) { | 532 | if (offset > 0) { |
536 | err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset); | 533 | err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset); |
537 | if (err && err != UBI_IO_BITFLIPS) { | 534 | if (err && err != UBI_IO_BITFLIPS) |
538 | vfree(new_buf); | ||
539 | goto out_put; | 535 | goto out_put; |
540 | } | ||
541 | } | 536 | } |
542 | 537 | ||
543 | memcpy(new_buf + offset, buf, len); | 538 | memcpy(ubi->peb_buf1 + offset, buf, len); |
544 | 539 | ||
545 | err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size); | 540 | err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size); |
546 | if (err) { | 541 | if (err) |
547 | vfree(new_buf); | ||
548 | goto write_error; | 542 | goto write_error; |
549 | } | ||
550 | 543 | ||
551 | vfree(new_buf); | 544 | mutex_unlock(&ubi->buf_mutex); |
552 | ubi_free_vid_hdr(ubi, vid_hdr); | 545 | ubi_free_vid_hdr(ubi, vid_hdr); |
553 | 546 | ||
554 | vol->eba_tbl[lnum] = new_pnum; | 547 | vol->eba_tbl[lnum] = new_pnum; |
@@ -558,6 +551,7 @@ retry: | |||
558 | return 0; | 551 | return 0; |
559 | 552 | ||
560 | out_put: | 553 | out_put: |
554 | mutex_unlock(&ubi->buf_mutex); | ||
561 | ubi_wl_put_peb(ubi, new_pnum, 1); | 555 | ubi_wl_put_peb(ubi, new_pnum, 1); |
562 | ubi_free_vid_hdr(ubi, vid_hdr); | 556 | ubi_free_vid_hdr(ubi, vid_hdr); |
563 | return err; | 557 | return err; |
@@ -570,6 +564,7 @@ write_error: | |||
570 | ubi_warn("failed to write to PEB %d", new_pnum); | 564 | ubi_warn("failed to write to PEB %d", new_pnum); |
571 | ubi_wl_put_peb(ubi, new_pnum, 1); | 565 | ubi_wl_put_peb(ubi, new_pnum, 1); |
572 | if (++tries > UBI_IO_RETRIES) { | 566 | if (++tries > UBI_IO_RETRIES) { |
567 | mutex_unlock(&ubi->buf_mutex); | ||
573 | ubi_free_vid_hdr(ubi, vid_hdr); | 568 | ubi_free_vid_hdr(ubi, vid_hdr); |
574 | return err; | 569 | return err; |
575 | } | 570 | } |
@@ -965,7 +960,6 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
965 | int err, vol_id, lnum, data_size, aldata_size, pnum, idx; | 960 | int err, vol_id, lnum, data_size, aldata_size, pnum, idx; |
966 | struct ubi_volume *vol; | 961 | struct ubi_volume *vol; |
967 | uint32_t crc; | 962 | uint32_t crc; |
968 | void *buf, *buf1 = NULL; | ||
969 | 963 | ||
970 | vol_id = be32_to_cpu(vid_hdr->vol_id); | 964 | vol_id = be32_to_cpu(vid_hdr->vol_id); |
971 | lnum = be32_to_cpu(vid_hdr->lnum); | 965 | lnum = be32_to_cpu(vid_hdr->lnum); |
@@ -979,19 +973,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
979 | data_size = aldata_size = | 973 | data_size = aldata_size = |
980 | ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); | 974 | ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); |
981 | 975 | ||
982 | buf = vmalloc(aldata_size); | ||
983 | if (!buf) | ||
984 | return -ENOMEM; | ||
985 | |||
986 | /* | 976 | /* |
987 | * We do not want anybody to write to this logical eraseblock while we | 977 | * We do not want anybody to write to this logical eraseblock while we |
988 | * are moving it, so we lock it. | 978 | * are moving it, so we lock it. |
989 | */ | 979 | */ |
990 | err = leb_write_lock(ubi, vol_id, lnum); | 980 | err = leb_write_lock(ubi, vol_id, lnum); |
991 | if (err) { | 981 | if (err) |
992 | vfree(buf); | ||
993 | return err; | 982 | return err; |
994 | } | 983 | |
984 | mutex_lock(&ubi->buf_mutex); | ||
995 | 985 | ||
996 | /* | 986 | /* |
997 | * But the logical eraseblock might have been put by this time. | 987 | * But the logical eraseblock might have been put by this time. |
@@ -1023,7 +1013,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1023 | /* OK, now the LEB is locked and we can safely start moving it */ | 1013 | /* OK, now the LEB is locked and we can safely start moving it */ |
1024 | 1014 | ||
1025 | dbg_eba("read %d bytes of data", aldata_size); | 1015 | dbg_eba("read %d bytes of data", aldata_size); |
1026 | err = ubi_io_read_data(ubi, buf, from, 0, aldata_size); | 1016 | err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size); |
1027 | if (err && err != UBI_IO_BITFLIPS) { | 1017 | if (err && err != UBI_IO_BITFLIPS) { |
1028 | ubi_warn("error %d while reading data from PEB %d", | 1018 | ubi_warn("error %d while reading data from PEB %d", |
1029 | err, from); | 1019 | err, from); |
@@ -1042,10 +1032,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1042 | */ | 1032 | */ |
1043 | if (vid_hdr->vol_type == UBI_VID_DYNAMIC) | 1033 | if (vid_hdr->vol_type == UBI_VID_DYNAMIC) |
1044 | aldata_size = data_size = | 1034 | aldata_size = data_size = |
1045 | ubi_calc_data_len(ubi, buf, data_size); | 1035 | ubi_calc_data_len(ubi, ubi->peb_buf1, data_size); |
1046 | 1036 | ||
1047 | cond_resched(); | 1037 | cond_resched(); |
1048 | crc = crc32(UBI_CRC32_INIT, buf, data_size); | 1038 | crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size); |
1049 | cond_resched(); | 1039 | cond_resched(); |
1050 | 1040 | ||
1051 | /* | 1041 | /* |
@@ -1076,23 +1066,18 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1076 | } | 1066 | } |
1077 | 1067 | ||
1078 | if (data_size > 0) { | 1068 | if (data_size > 0) { |
1079 | err = ubi_io_write_data(ubi, buf, to, 0, aldata_size); | 1069 | err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size); |
1080 | if (err) | 1070 | if (err) |
1081 | goto out_unlock; | 1071 | goto out_unlock; |
1082 | 1072 | ||
1073 | cond_resched(); | ||
1074 | |||
1083 | /* | 1075 | /* |
1084 | * We've written the data and are going to read it back to make | 1076 | * We've written the data and are going to read it back to make |
1085 | * sure it was written correctly. | 1077 | * sure it was written correctly. |
1086 | */ | 1078 | */ |
1087 | buf1 = vmalloc(aldata_size); | ||
1088 | if (!buf1) { | ||
1089 | err = -ENOMEM; | ||
1090 | goto out_unlock; | ||
1091 | } | ||
1092 | 1079 | ||
1093 | cond_resched(); | 1080 | err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); |
1094 | |||
1095 | err = ubi_io_read_data(ubi, buf1, to, 0, aldata_size); | ||
1096 | if (err) { | 1081 | if (err) { |
1097 | if (err != UBI_IO_BITFLIPS) | 1082 | if (err != UBI_IO_BITFLIPS) |
1098 | ubi_warn("cannot read data back from PEB %d", | 1083 | ubi_warn("cannot read data back from PEB %d", |
@@ -1102,7 +1087,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1102 | 1087 | ||
1103 | cond_resched(); | 1088 | cond_resched(); |
1104 | 1089 | ||
1105 | if (memcmp(buf, buf1, aldata_size)) { | 1090 | if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) { |
1106 | ubi_warn("read data back from PEB %d - it is different", | 1091 | ubi_warn("read data back from PEB %d - it is different", |
1107 | to); | 1092 | to); |
1108 | goto out_unlock; | 1093 | goto out_unlock; |
@@ -1112,16 +1097,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1112 | ubi_assert(vol->eba_tbl[lnum] == from); | 1097 | ubi_assert(vol->eba_tbl[lnum] == from); |
1113 | vol->eba_tbl[lnum] = to; | 1098 | vol->eba_tbl[lnum] = to; |
1114 | 1099 | ||
1115 | leb_write_unlock(ubi, vol_id, lnum); | ||
1116 | vfree(buf); | ||
1117 | vfree(buf1); | ||
1118 | |||
1119 | return 0; | ||
1120 | |||
1121 | out_unlock: | 1100 | out_unlock: |
1101 | mutex_unlock(&ubi->buf_mutex); | ||
1122 | leb_write_unlock(ubi, vol_id, lnum); | 1102 | leb_write_unlock(ubi, vol_id, lnum); |
1123 | vfree(buf); | ||
1124 | vfree(buf1); | ||
1125 | return err; | 1103 | return err; |
1126 | } | 1104 | } |
1127 | 1105 | ||