[Devel] [PATCH RHEL7 COMMIT] fuse kio: Fix unbalanced queueing and dequeueing pcs_map_entry::sync_work
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Jun 25 19:01:49 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.50.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.50.15
------>
commit 866950b8028871e9b461f1c987110bfdad631df6
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date: Mon Jun 25 19:01:49 2018 +0300
fuse kio: Fix unbalanced queueing and dequeueing pcs_map_entry::sync_work
timer_pending() can't be reliable indicator of delayed work
is queued. In case of timer has fired and the work has just
queued to workqueue, this code increments counter the second
time, while the work function will decrement it only once.
This patch makes counter incremented only in case of the work
has scheduled, and makes it decremented only in case of real
cancel has occured.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
Reviewed-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/kio/pcs/pcs_map.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 217644409528..a3bf48a8ea93 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -519,18 +519,21 @@ static void map_sync_work_add(struct pcs_map_entry *m, unsigned long timeout)
assert_spin_locked(&m->lock);
- if (!timer_pending(&m->sync_work.timer))
+ if (WARN_ON_ONCE(m->state & PCS_MAP_DEAD))
+ return;
+ /*
+ * Note, that work func takes m->lock on all paths,
+ * so it can't put map before we get it below.
+ */
+ if (!mod_delayed_work(cc->wq, &m->sync_work, timeout))
__pcs_map_get(m);
- mod_delayed_work(cc->wq, &m->sync_work, timeout);
}
static void map_sync_work_del(struct pcs_map_entry *m)
{
assert_spin_locked(&m->lock);
- if (!timer_pending(&m->sync_work.timer))
- return;
- cancel_delayed_work(&m->sync_work);
- pcs_map_put_locked(m);
+ if (cancel_delayed_work(&m->sync_work))
+ pcs_map_put_locked(m);
}
static void sync_timer_work(struct work_struct *w);
@@ -3049,7 +3052,8 @@ static void sync_timer_work(struct work_struct *w)
err = prepare_map_flush_ireq(m, &sreq);
if (err) {
spin_lock(&m->lock);
- map_sync_work_add(m, HZ);
+ if (!(m->state & PCS_MAP_DEAD))
+ map_sync_work_add(m, HZ);
spin_unlock(&m->lock);
} else {
if (sreq)
More information about the Devel
mailing list