aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2014-11-10 10:27:10 -0500
committerRichard Weinberger <richard@nod.at>2015-03-26 17:46:01 -0400
commit8fb2a514780eee48602424a86e3cd72d3f1bdfb2 (patch)
tree2c5c3bced155af20a7a27a2b368bc7c1df5586fa /drivers/mtd/ubi/eba.c
parentad3d6a05ee45eebf68ff08da0d3f86251b530a27 (diff)
UBI: Fastmap: Fix race after ubi_wl_get_peb()
ubi_wl_get_peb() returns a fresh PEB which can be used by user of UBI. Due to the pool logic fastmap will correctly map this PEB upon attach time because it will be scanned. If a new fastmap is written (due to heavy parallel io) while the before the fresh PEB is assigned to the EBA table it will not be scanned as it is no longer in the pool. So, the race window exists between ubi_wl_get_peb() and the EBA table assignment. We have to make sure that no new fastmap can be written while that. To ensure that ubi_wl_get_peb() will grab ubi->fm_sem in read mode and the user of ubi_wl_get_peb() has to release it after the PEB got assigned. Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r--drivers/mtd/ubi/eba.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index e0a06e4b95a4..4757cef756f7 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -567,6 +567,7 @@ retry:
567 new_pnum = ubi_wl_get_peb(ubi); 567 new_pnum = ubi_wl_get_peb(ubi);
568 if (new_pnum < 0) { 568 if (new_pnum < 0) {
569 ubi_free_vid_hdr(ubi, vid_hdr); 569 ubi_free_vid_hdr(ubi, vid_hdr);
570 up_read(&ubi->fm_sem);
570 return new_pnum; 571 return new_pnum;
571 } 572 }
572 573
@@ -577,13 +578,16 @@ retry:
577 if (err && err != UBI_IO_BITFLIPS) { 578 if (err && err != UBI_IO_BITFLIPS) {
578 if (err > 0) 579 if (err > 0)
579 err = -EIO; 580 err = -EIO;
581 up_read(&ubi->fm_sem);
580 goto out_put; 582 goto out_put;
581 } 583 }
582 584
583 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); 585 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
584 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); 586 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
585 if (err) 587 if (err) {
588 up_read(&ubi->fm_sem);
586 goto write_error; 589 goto write_error;
590 }
587 591
588 data_size = offset + len; 592 data_size = offset + len;
589 mutex_lock(&ubi->buf_mutex); 593 mutex_lock(&ubi->buf_mutex);
@@ -592,8 +596,10 @@ retry:
592 /* Read everything before the area where the write failure happened */ 596 /* Read everything before the area where the write failure happened */
593 if (offset > 0) { 597 if (offset > 0) {
594 err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset); 598 err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset);
595 if (err && err != UBI_IO_BITFLIPS) 599 if (err && err != UBI_IO_BITFLIPS) {
600 up_read(&ubi->fm_sem);
596 goto out_unlock; 601 goto out_unlock;
602 }
597 } 603 }
598 604
599 memcpy(ubi->peb_buf + offset, buf, len); 605 memcpy(ubi->peb_buf + offset, buf, len);
@@ -601,13 +607,13 @@ retry:
601 err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); 607 err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
602 if (err) { 608 if (err) {
603 mutex_unlock(&ubi->buf_mutex); 609 mutex_unlock(&ubi->buf_mutex);
610 up_read(&ubi->fm_sem);
604 goto write_error; 611 goto write_error;
605 } 612 }
606 613
607 mutex_unlock(&ubi->buf_mutex); 614 mutex_unlock(&ubi->buf_mutex);
608 ubi_free_vid_hdr(ubi, vid_hdr); 615 ubi_free_vid_hdr(ubi, vid_hdr);
609 616
610 down_read(&ubi->fm_sem);
611 vol->eba_tbl[lnum] = new_pnum; 617 vol->eba_tbl[lnum] = new_pnum;
612 up_read(&ubi->fm_sem); 618 up_read(&ubi->fm_sem);
613 ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); 619 ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
@@ -704,6 +710,7 @@ retry:
704 if (pnum < 0) { 710 if (pnum < 0) {
705 ubi_free_vid_hdr(ubi, vid_hdr); 711 ubi_free_vid_hdr(ubi, vid_hdr);
706 leb_write_unlock(ubi, vol_id, lnum); 712 leb_write_unlock(ubi, vol_id, lnum);
713 up_read(&ubi->fm_sem);
707 return pnum; 714 return pnum;
708 } 715 }
709 716
@@ -714,6 +721,7 @@ retry:
714 if (err) { 721 if (err) {
715 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", 722 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
716 vol_id, lnum, pnum); 723 vol_id, lnum, pnum);
724 up_read(&ubi->fm_sem);
717 goto write_error; 725 goto write_error;
718 } 726 }
719 727
@@ -722,11 +730,11 @@ retry:
722 if (err) { 730 if (err) {
723 ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d", 731 ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d",
724 len, offset, vol_id, lnum, pnum); 732 len, offset, vol_id, lnum, pnum);
733 up_read(&ubi->fm_sem);
725 goto write_error; 734 goto write_error;
726 } 735 }
727 } 736 }
728 737
729 down_read(&ubi->fm_sem);
730 vol->eba_tbl[lnum] = pnum; 738 vol->eba_tbl[lnum] = pnum;
731 up_read(&ubi->fm_sem); 739 up_read(&ubi->fm_sem);
732 740
@@ -825,6 +833,7 @@ retry:
825 if (pnum < 0) { 833 if (pnum < 0) {
826 ubi_free_vid_hdr(ubi, vid_hdr); 834 ubi_free_vid_hdr(ubi, vid_hdr);
827 leb_write_unlock(ubi, vol_id, lnum); 835 leb_write_unlock(ubi, vol_id, lnum);
836 up_read(&ubi->fm_sem);
828 return pnum; 837 return pnum;
829 } 838 }
830 839
@@ -835,6 +844,7 @@ retry:
835 if (err) { 844 if (err) {
836 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", 845 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
837 vol_id, lnum, pnum); 846 vol_id, lnum, pnum);
847 up_read(&ubi->fm_sem);
838 goto write_error; 848 goto write_error;
839 } 849 }
840 850
@@ -842,11 +852,11 @@ retry:
842 if (err) { 852 if (err) {
843 ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", 853 ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
844 len, pnum); 854 len, pnum);
855 up_read(&ubi->fm_sem);
845 goto write_error; 856 goto write_error;
846 } 857 }
847 858
848 ubi_assert(vol->eba_tbl[lnum] < 0); 859 ubi_assert(vol->eba_tbl[lnum] < 0);
849 down_read(&ubi->fm_sem);
850 vol->eba_tbl[lnum] = pnum; 860 vol->eba_tbl[lnum] = pnum;
851 up_read(&ubi->fm_sem); 861 up_read(&ubi->fm_sem);
852 862
@@ -943,6 +953,7 @@ retry:
943 pnum = ubi_wl_get_peb(ubi); 953 pnum = ubi_wl_get_peb(ubi);
944 if (pnum < 0) { 954 if (pnum < 0) {
945 err = pnum; 955 err = pnum;
956 up_read(&ubi->fm_sem);
946 goto out_leb_unlock; 957 goto out_leb_unlock;
947 } 958 }
948 959
@@ -953,6 +964,7 @@ retry:
953 if (err) { 964 if (err) {
954 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", 965 ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
955 vol_id, lnum, pnum); 966 vol_id, lnum, pnum);
967 up_read(&ubi->fm_sem);
956 goto write_error; 968 goto write_error;
957 } 969 }
958 970
@@ -960,10 +972,10 @@ retry:
960 if (err) { 972 if (err) {
961 ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", 973 ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
962 len, pnum); 974 len, pnum);
975 up_read(&ubi->fm_sem);
963 goto write_error; 976 goto write_error;
964 } 977 }
965 978
966 down_read(&ubi->fm_sem);
967 old_pnum = vol->eba_tbl[lnum]; 979 old_pnum = vol->eba_tbl[lnum];
968 vol->eba_tbl[lnum] = pnum; 980 vol->eba_tbl[lnum] = pnum;
969 up_read(&ubi->fm_sem); 981 up_read(&ubi->fm_sem);