aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2014-11-10 10:28:08 -0500
committerRichard Weinberger <richard@nod.at>2015-03-26 17:46:02 -0400
commit111ab0b26fc1bfad575d1e376e146d194d261e22 (patch)
tree451a0a31b6f28d85986569010fa8c3381eb1d622 /drivers/mtd
parent42dd3cdcd6b5671ebedc3df76ca8dcc3473bcc67 (diff)
UBI: Fastmap: Locking updates
a) Rename ubi->fm_sem to ubi->fm_eba_sem as this semaphore protects EBA changes. b) Turn ubi->fm_mutex into a rw semaphore. It will still serialize fastmap writes but also ensures that ubi_wl_put_peb() is not interrupted by a fastmap write. We use a rw semaphore to allow ubi_wl_put_peb() still to be executed in parallel if no fastmap write is happening. Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/build.c4
-rw-r--r--drivers/mtd/ubi/eba.c44
-rw-r--r--drivers/mtd/ubi/fastmap.c18
-rw-r--r--drivers/mtd/ubi/ubi.h9
-rw-r--r--drivers/mtd/ubi/wl.c19
5 files changed, 50 insertions, 44 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 59af91b41f9a..a7571508fdab 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -969,8 +969,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
969 mutex_init(&ubi->ckvol_mutex); 969 mutex_init(&ubi->ckvol_mutex);
970 mutex_init(&ubi->device_mutex); 970 mutex_init(&ubi->device_mutex);
971 spin_lock_init(&ubi->volumes_lock); 971 spin_lock_init(&ubi->volumes_lock);
972 mutex_init(&ubi->fm_mutex); 972 init_rwsem(&ubi->fm_protect);
973 init_rwsem(&ubi->fm_sem); 973 init_rwsem(&ubi->fm_eba_sem);
974 974
975 ubi_msg(ubi, "attaching mtd%d", mtd->index); 975 ubi_msg(ubi, "attaching mtd%d", mtd->index);
976 976
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 4757cef756f7..51bca035cd83 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -340,9 +340,9 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
340 340
341 dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); 341 dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
342 342
343 down_read(&ubi->fm_sem); 343 down_read(&ubi->fm_eba_sem);
344 vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; 344 vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
345 up_read(&ubi->fm_sem); 345 up_read(&ubi->fm_eba_sem);
346 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0); 346 err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
347 347
348out_unlock: 348out_unlock:
@@ -567,7 +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 up_read(&ubi->fm_eba_sem);
571 return new_pnum; 571 return new_pnum;
572 } 572 }
573 573
@@ -578,14 +578,14 @@ retry:
578 if (err && err != UBI_IO_BITFLIPS) { 578 if (err && err != UBI_IO_BITFLIPS) {
579 if (err > 0) 579 if (err > 0)
580 err = -EIO; 580 err = -EIO;
581 up_read(&ubi->fm_sem); 581 up_read(&ubi->fm_eba_sem);
582 goto out_put; 582 goto out_put;
583 } 583 }
584 584
585 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); 585 vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
586 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); 586 err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
587 if (err) { 587 if (err) {
588 up_read(&ubi->fm_sem); 588 up_read(&ubi->fm_eba_sem);
589 goto write_error; 589 goto write_error;
590 } 590 }
591 591
@@ -597,7 +597,7 @@ retry:
597 if (offset > 0) { 597 if (offset > 0) {
598 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);
599 if (err && err != UBI_IO_BITFLIPS) { 599 if (err && err != UBI_IO_BITFLIPS) {
600 up_read(&ubi->fm_sem); 600 up_read(&ubi->fm_eba_sem);
601 goto out_unlock; 601 goto out_unlock;
602 } 602 }
603 } 603 }
@@ -607,7 +607,7 @@ retry:
607 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);
608 if (err) { 608 if (err) {
609 mutex_unlock(&ubi->buf_mutex); 609 mutex_unlock(&ubi->buf_mutex);
610 up_read(&ubi->fm_sem); 610 up_read(&ubi->fm_eba_sem);
611 goto write_error; 611 goto write_error;
612 } 612 }
613 613
@@ -615,7 +615,7 @@ retry:
615 ubi_free_vid_hdr(ubi, vid_hdr); 615 ubi_free_vid_hdr(ubi, vid_hdr);
616 616
617 vol->eba_tbl[lnum] = new_pnum; 617 vol->eba_tbl[lnum] = new_pnum;
618 up_read(&ubi->fm_sem); 618 up_read(&ubi->fm_eba_sem);
619 ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); 619 ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
620 620
621 ubi_msg(ubi, "data was successfully recovered"); 621 ubi_msg(ubi, "data was successfully recovered");
@@ -710,7 +710,7 @@ retry:
710 if (pnum < 0) { 710 if (pnum < 0) {
711 ubi_free_vid_hdr(ubi, vid_hdr); 711 ubi_free_vid_hdr(ubi, vid_hdr);
712 leb_write_unlock(ubi, vol_id, lnum); 712 leb_write_unlock(ubi, vol_id, lnum);
713 up_read(&ubi->fm_sem); 713 up_read(&ubi->fm_eba_sem);
714 return pnum; 714 return pnum;
715 } 715 }
716 716
@@ -721,7 +721,7 @@ retry:
721 if (err) { 721 if (err) {
722 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",
723 vol_id, lnum, pnum); 723 vol_id, lnum, pnum);
724 up_read(&ubi->fm_sem); 724 up_read(&ubi->fm_eba_sem);
725 goto write_error; 725 goto write_error;
726 } 726 }
727 727
@@ -730,13 +730,13 @@ retry:
730 if (err) { 730 if (err) {
731 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",
732 len, offset, vol_id, lnum, pnum); 732 len, offset, vol_id, lnum, pnum);
733 up_read(&ubi->fm_sem); 733 up_read(&ubi->fm_eba_sem);
734 goto write_error; 734 goto write_error;
735 } 735 }
736 } 736 }
737 737
738 vol->eba_tbl[lnum] = pnum; 738 vol->eba_tbl[lnum] = pnum;
739 up_read(&ubi->fm_sem); 739 up_read(&ubi->fm_eba_sem);
740 740
741 leb_write_unlock(ubi, vol_id, lnum); 741 leb_write_unlock(ubi, vol_id, lnum);
742 ubi_free_vid_hdr(ubi, vid_hdr); 742 ubi_free_vid_hdr(ubi, vid_hdr);
@@ -833,7 +833,7 @@ retry:
833 if (pnum < 0) { 833 if (pnum < 0) {
834 ubi_free_vid_hdr(ubi, vid_hdr); 834 ubi_free_vid_hdr(ubi, vid_hdr);
835 leb_write_unlock(ubi, vol_id, lnum); 835 leb_write_unlock(ubi, vol_id, lnum);
836 up_read(&ubi->fm_sem); 836 up_read(&ubi->fm_eba_sem);
837 return pnum; 837 return pnum;
838 } 838 }
839 839
@@ -844,7 +844,7 @@ retry:
844 if (err) { 844 if (err) {
845 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",
846 vol_id, lnum, pnum); 846 vol_id, lnum, pnum);
847 up_read(&ubi->fm_sem); 847 up_read(&ubi->fm_eba_sem);
848 goto write_error; 848 goto write_error;
849 } 849 }
850 850
@@ -852,13 +852,13 @@ retry:
852 if (err) { 852 if (err) {
853 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",
854 len, pnum); 854 len, pnum);
855 up_read(&ubi->fm_sem); 855 up_read(&ubi->fm_eba_sem);
856 goto write_error; 856 goto write_error;
857 } 857 }
858 858
859 ubi_assert(vol->eba_tbl[lnum] < 0); 859 ubi_assert(vol->eba_tbl[lnum] < 0);
860 vol->eba_tbl[lnum] = pnum; 860 vol->eba_tbl[lnum] = pnum;
861 up_read(&ubi->fm_sem); 861 up_read(&ubi->fm_eba_sem);
862 862
863 leb_write_unlock(ubi, vol_id, lnum); 863 leb_write_unlock(ubi, vol_id, lnum);
864 ubi_free_vid_hdr(ubi, vid_hdr); 864 ubi_free_vid_hdr(ubi, vid_hdr);
@@ -953,7 +953,7 @@ retry:
953 pnum = ubi_wl_get_peb(ubi); 953 pnum = ubi_wl_get_peb(ubi);
954 if (pnum < 0) { 954 if (pnum < 0) {
955 err = pnum; 955 err = pnum;
956 up_read(&ubi->fm_sem); 956 up_read(&ubi->fm_eba_sem);
957 goto out_leb_unlock; 957 goto out_leb_unlock;
958 } 958 }
959 959
@@ -964,7 +964,7 @@ retry:
964 if (err) { 964 if (err) {
965 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",
966 vol_id, lnum, pnum); 966 vol_id, lnum, pnum);
967 up_read(&ubi->fm_sem); 967 up_read(&ubi->fm_eba_sem);
968 goto write_error; 968 goto write_error;
969 } 969 }
970 970
@@ -972,13 +972,13 @@ retry:
972 if (err) { 972 if (err) {
973 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",
974 len, pnum); 974 len, pnum);
975 up_read(&ubi->fm_sem); 975 up_read(&ubi->fm_eba_sem);
976 goto write_error; 976 goto write_error;
977 } 977 }
978 978
979 old_pnum = vol->eba_tbl[lnum]; 979 old_pnum = vol->eba_tbl[lnum];
980 vol->eba_tbl[lnum] = pnum; 980 vol->eba_tbl[lnum] = pnum;
981 up_read(&ubi->fm_sem); 981 up_read(&ubi->fm_eba_sem);
982 982
983 if (old_pnum >= 0) { 983 if (old_pnum >= 0) {
984 err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0); 984 err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0);
@@ -1231,9 +1231,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1231 } 1231 }
1232 1232
1233 ubi_assert(vol->eba_tbl[lnum] == from); 1233 ubi_assert(vol->eba_tbl[lnum] == from);
1234 down_read(&ubi->fm_sem); 1234 down_read(&ubi->fm_eba_sem);
1235 vol->eba_tbl[lnum] = to; 1235 vol->eba_tbl[lnum] = to;
1236 up_read(&ubi->fm_sem); 1236 up_read(&ubi->fm_eba_sem);
1237 1237
1238out_unlock_buf: 1238out_unlock_buf:
1239 mutex_unlock(&ubi->buf_mutex); 1239 mutex_unlock(&ubi->buf_mutex);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 749e2e4738fc..2cf2506b8f44 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -800,7 +800,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
800 __be32 crc, tmp_crc; 800 __be32 crc, tmp_crc;
801 unsigned long long sqnum = 0; 801 unsigned long long sqnum = 0;
802 802
803 mutex_lock(&ubi->fm_mutex); 803 down_write(&ubi->fm_protect);
804 memset(ubi->fm_buf, 0, ubi->fm_size); 804 memset(ubi->fm_buf, 0, ubi->fm_size);
805 805
806 fmsb = kmalloc(sizeof(*fmsb), GFP_KERNEL); 806 fmsb = kmalloc(sizeof(*fmsb), GFP_KERNEL);
@@ -991,7 +991,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
991 ubi_free_vid_hdr(ubi, vh); 991 ubi_free_vid_hdr(ubi, vh);
992 kfree(ech); 992 kfree(ech);
993out: 993out:
994 mutex_unlock(&ubi->fm_mutex); 994 up_write(&ubi->fm_protect);
995 if (ret == UBI_BAD_FASTMAP) 995 if (ret == UBI_BAD_FASTMAP)
996 ubi_err(ubi, "Attach by fastmap failed, doing a full scan!"); 996 ubi_err(ubi, "Attach by fastmap failed, doing a full scan!");
997 return ret; 997 return ret;
@@ -1340,24 +1340,24 @@ int ubi_update_fastmap(struct ubi_device *ubi)
1340 struct ubi_fastmap_layout *new_fm, *old_fm; 1340 struct ubi_fastmap_layout *new_fm, *old_fm;
1341 struct ubi_wl_entry *tmp_e; 1341 struct ubi_wl_entry *tmp_e;
1342 1342
1343 mutex_lock(&ubi->fm_mutex); 1343 down_write(&ubi->fm_protect);
1344 1344
1345 ubi_refill_pools(ubi); 1345 ubi_refill_pools(ubi);
1346 1346
1347 if (ubi->ro_mode || ubi->fm_disabled) { 1347 if (ubi->ro_mode || ubi->fm_disabled) {
1348 mutex_unlock(&ubi->fm_mutex); 1348 up_write(&ubi->fm_protect);
1349 return 0; 1349 return 0;
1350 } 1350 }
1351 1351
1352 ret = ubi_ensure_anchor_pebs(ubi); 1352 ret = ubi_ensure_anchor_pebs(ubi);
1353 if (ret) { 1353 if (ret) {
1354 mutex_unlock(&ubi->fm_mutex); 1354 up_write(&ubi->fm_protect);
1355 return ret; 1355 return ret;
1356 } 1356 }
1357 1357
1358 new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL); 1358 new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
1359 if (!new_fm) { 1359 if (!new_fm) {
1360 mutex_unlock(&ubi->fm_mutex); 1360 up_write(&ubi->fm_protect);
1361 return -ENOMEM; 1361 return -ENOMEM;
1362 } 1362 }
1363 1363
@@ -1447,16 +1447,16 @@ int ubi_update_fastmap(struct ubi_device *ubi)
1447 } 1447 }
1448 1448
1449 down_write(&ubi->work_sem); 1449 down_write(&ubi->work_sem);
1450 down_write(&ubi->fm_sem); 1450 down_write(&ubi->fm_eba_sem);
1451 ret = ubi_write_fastmap(ubi, new_fm); 1451 ret = ubi_write_fastmap(ubi, new_fm);
1452 up_write(&ubi->fm_sem); 1452 up_write(&ubi->fm_eba_sem);
1453 up_write(&ubi->work_sem); 1453 up_write(&ubi->work_sem);
1454 1454
1455 if (ret) 1455 if (ret)
1456 goto err; 1456 goto err;
1457 1457
1458out_unlock: 1458out_unlock:
1459 mutex_unlock(&ubi->fm_mutex); 1459 up_write(&ubi->fm_protect);
1460 kfree(old_fm); 1460 kfree(old_fm);
1461 return ret; 1461 return ret;
1462 1462
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 3ea9480bd055..058c84cac8dc 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -426,10 +426,11 @@ struct ubi_debug_info {
426 * @fm_pool: in-memory data structure of the fastmap pool 426 * @fm_pool: in-memory data structure of the fastmap pool
427 * @fm_wl_pool: in-memory data structure of the fastmap pool used by the WL 427 * @fm_wl_pool: in-memory data structure of the fastmap pool used by the WL
428 * sub-system 428 * sub-system
429 * @fm_mutex: serializes ubi_update_fastmap() and protects @fm_buf 429 * @fm_protect: serializes ubi_update_fastmap(), protects @fm_buf and makes sure
430 * that critical sections cannot be interrupted by ubi_update_fastmap()
430 * @fm_buf: vmalloc()'d buffer which holds the raw fastmap 431 * @fm_buf: vmalloc()'d buffer which holds the raw fastmap
431 * @fm_size: fastmap size in bytes 432 * @fm_size: fastmap size in bytes
432 * @fm_sem: allows ubi_update_fastmap() to block EBA table changes 433 * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes
433 * @fm_work: fastmap work queue 434 * @fm_work: fastmap work queue
434 * @fm_work_scheduled: non-zero if fastmap work was scheduled 435 * @fm_work_scheduled: non-zero if fastmap work was scheduled
435 * 436 *
@@ -534,8 +535,8 @@ struct ubi_device {
534 struct ubi_fastmap_layout *fm; 535 struct ubi_fastmap_layout *fm;
535 struct ubi_fm_pool fm_pool; 536 struct ubi_fm_pool fm_pool;
536 struct ubi_fm_pool fm_wl_pool; 537 struct ubi_fm_pool fm_wl_pool;
537 struct rw_semaphore fm_sem; 538 struct rw_semaphore fm_eba_sem;
538 struct mutex fm_mutex; 539 struct rw_semaphore fm_protect;
539 void *fm_buf; 540 void *fm_buf;
540 size_t fm_size; 541 size_t fm_size;
541 struct work_struct fm_work; 542 struct work_struct fm_work;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index b8ad5e005cdc..609b16d45406 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -641,7 +641,7 @@ void ubi_refill_pools(struct ubi_device *ubi)
641 641
642/* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of 642/* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of
643 * the fastmap pool. 643 * the fastmap pool.
644 * Returns with ubi->fm_sem held in read mode! 644 * Returns with ubi->fm_eba_sem held in read mode!
645 */ 645 */
646int ubi_wl_get_peb(struct ubi_device *ubi) 646int ubi_wl_get_peb(struct ubi_device *ubi)
647{ 647{
@@ -650,20 +650,20 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
650 struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; 650 struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
651 651
652again: 652again:
653 down_read(&ubi->fm_sem); 653 down_read(&ubi->fm_eba_sem);
654 spin_lock(&ubi->wl_lock); 654 spin_lock(&ubi->wl_lock);
655 /* We check here also for the WL pool because at this point we can 655 /* We check here also for the WL pool because at this point we can
656 * refill the WL pool synchronous. */ 656 * refill the WL pool synchronous. */
657 if (pool->used == pool->size || wl_pool->used == wl_pool->size) { 657 if (pool->used == pool->size || wl_pool->used == wl_pool->size) {
658 spin_unlock(&ubi->wl_lock); 658 spin_unlock(&ubi->wl_lock);
659 up_read(&ubi->fm_sem); 659 up_read(&ubi->fm_eba_sem);
660 ret = ubi_update_fastmap(ubi); 660 ret = ubi_update_fastmap(ubi);
661 if (ret) { 661 if (ret) {
662 ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); 662 ubi_msg(ubi, "Unable to write a new fastmap: %i", ret);
663 down_read(&ubi->fm_sem); 663 down_read(&ubi->fm_eba_sem);
664 return -ENOSPC; 664 return -ENOSPC;
665 } 665 }
666 down_read(&ubi->fm_sem); 666 down_read(&ubi->fm_eba_sem);
667 spin_lock(&ubi->wl_lock); 667 spin_lock(&ubi->wl_lock);
668 } 668 }
669 669
@@ -675,7 +675,7 @@ again:
675 goto out; 675 goto out;
676 } 676 }
677 retried = 1; 677 retried = 1;
678 up_read(&ubi->fm_sem); 678 up_read(&ubi->fm_eba_sem);
679 goto again; 679 goto again;
680 } 680 }
681 681
@@ -731,7 +731,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
731 spin_lock(&ubi->wl_lock); 731 spin_lock(&ubi->wl_lock);
732 peb = wl_get_peb(ubi); 732 peb = wl_get_peb(ubi);
733 spin_unlock(&ubi->wl_lock); 733 spin_unlock(&ubi->wl_lock);
734 down_read(&ubi->fm_sem); 734 down_read(&ubi->fm_eba_sem);
735 735
736 if (peb < 0) 736 if (peb < 0)
737 return peb; 737 return peb;
@@ -1607,6 +1607,8 @@ int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
1607 ubi_assert(pnum >= 0); 1607 ubi_assert(pnum >= 0);
1608 ubi_assert(pnum < ubi->peb_count); 1608 ubi_assert(pnum < ubi->peb_count);
1609 1609
1610 down_read(&ubi->fm_protect);
1611
1610retry: 1612retry:
1611 spin_lock(&ubi->wl_lock); 1613 spin_lock(&ubi->wl_lock);
1612 e = ubi->lookuptbl[pnum]; 1614 e = ubi->lookuptbl[pnum];
@@ -1637,6 +1639,7 @@ retry:
1637 ubi_assert(!ubi->move_to_put); 1639 ubi_assert(!ubi->move_to_put);
1638 ubi->move_to_put = 1; 1640 ubi->move_to_put = 1;
1639 spin_unlock(&ubi->wl_lock); 1641 spin_unlock(&ubi->wl_lock);
1642 up_read(&ubi->fm_protect);
1640 return 0; 1643 return 0;
1641 } else { 1644 } else {
1642 if (in_wl_tree(e, &ubi->used)) { 1645 if (in_wl_tree(e, &ubi->used)) {
@@ -1658,6 +1661,7 @@ retry:
1658 ubi_err(ubi, "PEB %d not found", pnum); 1661 ubi_err(ubi, "PEB %d not found", pnum);
1659 ubi_ro_mode(ubi); 1662 ubi_ro_mode(ubi);
1660 spin_unlock(&ubi->wl_lock); 1663 spin_unlock(&ubi->wl_lock);
1664 up_read(&ubi->fm_protect);
1661 return err; 1665 return err;
1662 } 1666 }
1663 } 1667 }
@@ -1671,6 +1675,7 @@ retry:
1671 spin_unlock(&ubi->wl_lock); 1675 spin_unlock(&ubi->wl_lock);
1672 } 1676 }
1673 1677
1678 up_read(&ubi->fm_protect);
1674 return err; 1679 return err;
1675} 1680}
1676 1681