diff options
author | Richard Weinberger <richard@nod.at> | 2014-11-10 16:28:08 +0100 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2015-03-26 22:46:02 +0100 |
commit | 111ab0b26fc1bfad575d1e376e146d194d261e22 (patch) | |
tree | 451a0a31b6f28d85986569010fa8c3381eb1d622 /drivers/mtd/ubi/wl.c | |
parent | 42dd3cdcd6b5671ebedc3df76ca8dcc3473bcc67 (diff) | |
download | linux-stable-111ab0b26fc1bfad575d1e376e146d194d261e22.tar.gz linux-stable-111ab0b26fc1bfad575d1e376e146d194d261e22.tar.bz2 linux-stable-111ab0b26fc1bfad575d1e376e146d194d261e22.zip |
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/ubi/wl.c')
-rw-r--r-- | drivers/mtd/ubi/wl.c | 19 |
1 files changed, 12 insertions, 7 deletions
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) /* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of * the fastmap pool. - * Returns with ubi->fm_sem held in read mode! + * Returns with ubi->fm_eba_sem held in read mode! */ int ubi_wl_get_peb(struct ubi_device *ubi) { @@ -650,20 +650,20 @@ int ubi_wl_get_peb(struct ubi_device *ubi) struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; again: - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); spin_lock(&ubi->wl_lock); /* We check here also for the WL pool because at this point we can * refill the WL pool synchronous. */ if (pool->used == pool->size || wl_pool->used == wl_pool->size) { spin_unlock(&ubi->wl_lock); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); ret = ubi_update_fastmap(ubi); if (ret) { ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); return -ENOSPC; } - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); spin_lock(&ubi->wl_lock); } @@ -675,7 +675,7 @@ again: goto out; } retried = 1; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto again; } @@ -731,7 +731,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi) spin_lock(&ubi->wl_lock); peb = wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); if (peb < 0) return peb; @@ -1607,6 +1607,8 @@ int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, ubi_assert(pnum >= 0); ubi_assert(pnum < ubi->peb_count); + down_read(&ubi->fm_protect); + retry: spin_lock(&ubi->wl_lock); e = ubi->lookuptbl[pnum]; @@ -1637,6 +1639,7 @@ retry: ubi_assert(!ubi->move_to_put); ubi->move_to_put = 1; spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_protect); return 0; } else { if (in_wl_tree(e, &ubi->used)) { @@ -1658,6 +1661,7 @@ retry: ubi_err(ubi, "PEB %d not found", pnum); ubi_ro_mode(ubi); spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_protect); return err; } } @@ -1671,6 +1675,7 @@ retry: spin_unlock(&ubi->wl_lock); } + up_read(&ubi->fm_protect); return err; } |