summaryrefslogtreecommitdiff
path: root/drivers/mtd/ubi/wl.c
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2014-11-10 16:28:08 +0100
committerRichard Weinberger <richard@nod.at>2015-03-26 22:46:02 +0100
commit111ab0b26fc1bfad575d1e376e146d194d261e22 (patch)
tree451a0a31b6f28d85986569010fa8c3381eb1d622 /drivers/mtd/ubi/wl.c
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/ubi/wl.c')
-rw-r--r--drivers/mtd/ubi/wl.c19
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;
}