aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-06-20 18:31:50 -0400
committerRichard Weinberger <richard@nod.at>2016-06-22 18:29:32 -0400
commit972228d87445dc46c0a01f5f3de673ac017626f7 (patch)
tree41cf6d89bcc2899d00d52b46d4333179f4903e50 /drivers/mtd/ubi
parentc0a1ecb9f4e208f4b75d88fa9669748e3fd705ab (diff)
ubi: Make recover_peb power cut aware
recover_peb() was never power cut aware, if a power cut happened right after writing the VID header upon next attach UBI would blindly use the new partial written PEB and all data from the old PEB is lost. In order to make recover_peb() power cut aware, write the new VID with a proper crc and copy_flag set such that the UBI attach process will detect whether the new PEB is completely written or not. We cannot directly use ubi_eba_atomic_leb_change() since we'd have to unlock the LEB which is facing a write error. Cc: stable@vger.kernel.org Reported-by: Jörg Pfähler <pfaehler@isse.de> Reviewed-by: Jörg Pfähler <pfaehler@isse.de> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/eba.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 5780dd1ba79d..ebf517271d29 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -575,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
575 int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; 575 int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
576 struct ubi_volume *vol = ubi->volumes[idx]; 576 struct ubi_volume *vol = ubi->volumes[idx];
577 struct ubi_vid_hdr *vid_hdr; 577 struct ubi_vid_hdr *vid_hdr;
578 uint32_t crc;
578 579
579 vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); 580 vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
580 if (!vid_hdr) 581 if (!vid_hdr)
@@ -599,14 +600,8 @@ retry:
599 goto out_put; 600 goto out_put;
600 } 601 }
601 602
602 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); 603 ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
603 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
604 if (err) {
605 up_read(&ubi->fm_eba_sem);
606 goto write_error;
607 }
608 604
609 data_size = offset + len;
610 mutex_lock(&ubi->buf_mutex); 605 mutex_lock(&ubi->buf_mutex);
611 memset(ubi->peb_buf + offset, 0xFF, len); 606 memset(ubi->peb_buf + offset, 0xFF, len);
612 607
@@ -621,6 +616,19 @@ retry:
621 616
622 memcpy(ubi->peb_buf + offset, buf, len); 617 memcpy(ubi->peb_buf + offset, buf, len);
623 618
619 data_size = offset + len;
620 crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
621 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
622 vid_hdr->copy_flag = 1;
623 vid_hdr->data_size = cpu_to_be32(data_size);
624 vid_hdr->data_crc = cpu_to_be32(crc);
625 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
626 if (err) {
627 mutex_unlock(&ubi->buf_mutex);
628 up_read(&ubi->fm_eba_sem);
629 goto write_error;
630 }
631
624 err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); 632 err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
625 if (err) { 633 if (err) {
626 mutex_unlock(&ubi->buf_mutex); 634 mutex_unlock(&ubi->buf_mutex);