[Devel] [PATCH RHEL7 COMMIT] fuse kio: Do not NULL used pcs_cs_link::cs during connection destruction
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Jun 15 15:04:47 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.9
------>
commit ae1cd3dd47d1cbc2acee8f3e89181a7641dd8531
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date: Fri Jun 15 15:04:47 2018 +0300
fuse kio: Do not NULL used pcs_cs_link::cs during connection destruction
fuse kio: Do not NULL used pcs_cs_link::cs during connection destruction
From: Kirill Tkhai <ktkhai at virtuozzo.com>
Some inodes may have assigned maps. They are evicted later
than pcs_cs_isolate() NULLes pcs_cs_link::cs pointers. So,
we mustn't have maps after pcs_cs_isolate() is finished.
This patch makes pcs_cs_link::cs be NULLed in generic way,
i.e. after the last reference to the list is dropped (via
cslist_put()).
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
Acked-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
Reviewed-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/kio/pcs/pcs_cs.c | 10 +--------
fs/fuse/kio/pcs/pcs_map.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
fs/fuse/kio/pcs/pcs_map.h | 1 +
3 files changed, 56 insertions(+), 9 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index b65e16be9f85..8345e92c4570 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -726,15 +726,7 @@ static void pcs_cs_isolate(struct pcs_cs *cs, struct list_head *dispose)
cancel_delayed_work(&cs->css->bl_work);
spin_unlock(&cs->css->lock);
- while (!list_empty(&cs->map_list)) {
- struct pcs_cs_link *csl = list_first_entry(&cs->map_list,
- struct pcs_cs_link,
- link);
- rcu_assign_pointer(csl->cs, NULL);
- cs->nmaps--;
- list_del_init(&csl->link);
- }
-
+ pcs_cs_truncate_maps(cs);
BUG_ON(cs->nmaps);
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index f20db1d5b3f9..8b8d81dae163 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -267,6 +267,60 @@ void map_truncate_tail(struct pcs_mapping * mapping, u64 offset)
pcs_ireq_queue_fail(&dispose, PCS_ERR_NET_ABORT);
}
+void pcs_cs_truncate_maps(struct pcs_cs *cs)
+{
+ struct pcs_cs_list *cs_list;
+ struct pcs_cs_link *cs_link;
+ struct pcs_map_entry *m;
+ LIST_HEAD(map_list);
+ bool once = true;
+
+ cs->use_count++;
+again:
+ lockdep_assert_held(&cs->lock);
+
+ while (!list_empty(&cs->map_list)) {
+ cs_link = list_first_entry(&cs->map_list,
+ struct pcs_cs_link, link);
+ list_move(&cs_link->link, &map_list);
+
+ cs_list = cs_link_to_cs_list(cs_link);
+ cslist_get(cs_list);
+ spin_unlock(&cs->lock);
+
+ rcu_read_lock();
+ m = rcu_dereference(cs_list->map);
+ if (!m)
+ goto skip;
+ spin_lock(&m->lock);
+ if (!list_empty(&m->queue)) {
+ WARN(once, "Not empty map queue\n");
+ once = false;
+ } else if (!(m->state & PCS_MAP_DEAD)) {
+ pcs_map_truncate(m, NULL);
+ map_del_lru(m);
+ }
+ spin_unlock(&m->lock);
+skip:
+ rcu_read_unlock();
+ /*
+ * cs_link will be removed from map_list
+ * on the final cslist_put(). Maybe now.
+ */
+ cslist_put(cs_list);
+ spin_lock(&cs->lock);
+ }
+
+ list_splice(&map_list, &cs->map_list);
+ if (!list_empty(&cs->map_list)) {
+ spin_unlock(&cs->lock);
+ schedule_timeout_uninterruptible(HZ);
+ spin_lock(&cs->lock);
+ goto again;
+ }
+ cs->use_count--;
+}
+
void pcs_mapping_invalidate(struct pcs_mapping * mapping)
{
pcs_mapping_dump(mapping);
diff --git a/fs/fuse/kio/pcs/pcs_map.h b/fs/fuse/kio/pcs/pcs_map.h
index bc36983a7355..3eb380bd0b07 100644
--- a/fs/fuse/kio/pcs/pcs_map.h
+++ b/fs/fuse/kio/pcs/pcs_map.h
@@ -190,6 +190,7 @@ struct pcs_ioc_getmap;
void pcs_map_complete(struct pcs_map_entry *m, struct pcs_ioc_getmap *omap);
int pcs_map_encode_req(struct pcs_map_entry*m, struct pcs_ioc_getmap *map, int direction);
void map_truncate_tail(struct pcs_mapping *mapping, u64 offset);
+void pcs_cs_truncate_maps(struct pcs_cs *cs);
unsigned long pcs_map_shrink_scan(struct shrinker *, struct shrink_control *sc);
void ireq_drop_tokens(struct pcs_int_request * ireq);
More information about the Devel
mailing list