The commit is pushed to "branch-rh10-6.12.0-55.13.1.2.x.vz10-ovz" and will
appear at [email protected]:openvz/vzkernel.git
after rh10-6.12.0-55.13.1.2.16.vz10
------>
commit fb58e8825e1dec4848b58045076a780fde72e870
Author: Liu Kui <[email protected]>
Date: Thu Nov 6 10:14:20 2025 +0800
fs/fuse/kio: fix unwarranted warning due to flush request race
The warning in pcs_map_queue_resolve() was triggered not by an expected
bug, but due to a race in processing flush requests originating from the
timer.
Straighten out the map resolve process flow to fix the race by avoiding
repeated lock/unlock of the map lock across several functions.
Additionally, promote the warning condition in pcs_map_queue_resolve() to
an assertion in map_submit() to trigger a coredump if the condition truly
occurs.
https://virtuozzo.atlassian.net/browse/VSTOR-116825
Signed-off-by: Liu Kui <[email protected]>
Acked-by: Alexey Kuznetsov <[email protected]>
Feature: vStorage
---
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 11 -----
fs/fuse/kio/pcs/pcs_map.c | 91 ++++++++++++++++++--------------------
2 files changed, 44 insertions(+), 58 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index e97f95e7947fd..eafe2ee2313b7 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -601,22 +601,11 @@ int fuse_map_resolve(struct pcs_map_entry *m, int
direction)
size_t map_sz;
int err;
- spin_lock(&m->lock);
-
- if (m->state & PCS_MAP_DEAD) {
- spin_unlock(&m->lock);
- pcs_map_put(m);
- return 0;
- }
di = pcs_dentry_from_mapping(m->mapping);
fm = get_fuse_mount(&di->inode->inode);
DTRACE("enter m: " MAP_FMT ", dir:%d \n", MAP_ARGS(m), direction);
- BUG_ON(!(m->state & PCS_MAP_RESOLVING));
-
- spin_unlock(&m->lock);
-
map_sz = sizeof(*map_ioc) + PCS_MAX_CS_CNT * sizeof(struct pcs_cs_info);
map_ioc = kzalloc(map_sz, GFP_NOIO);
if (!map_ioc)
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 44e463a61c3f2..ac9367eaeba39 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -1265,23 +1265,14 @@ void pcs_map_complete(struct pcs_map_entry *m, struct
pcs_ioc_getmap *omap)
/* Atomically schedule map resolve and push ireq to wait completion */
static void pcs_map_queue_resolve(struct pcs_map_entry * m, struct
pcs_int_request *ireq, int direction)
+__releases(m->lock)
{
LIST_HEAD(l);
int ret;
- DTRACE("enter m:%p, state:%x, ireq:%p dir:%d \n", m, m->state, ireq,
direction);
-
- spin_lock(&m->lock);
- /* This should not happen unless aio_dio/fsync vs truncate race */
- if (m->state & PCS_MAP_DEAD) {
- spin_unlock(&m->lock);
+ assert_spin_locked(&m->lock);
- /* If this happens, it's assumed this is a bug that needs to be
fixed */
- WARN_ON_ONCE(1);
- list_add(&ireq->list, &l);
- pcs_ireq_queue_fail(&l, PCS_ERR_NET_ABORT);
- return;
- }
+ DTRACE("enter m:%p, state:%x, ireq:%p dir:%d \n", m, m->state, ireq,
direction);
DTRACE("dentry: "DENTRY_FMT, DENTRY_ARGS(pcs_dentry_from_map(m)));
DTRACE("%p {%p %p}\n",ireq, ireq->list.next, ireq->list.prev);
BUG_ON(!list_empty(&ireq->list));
@@ -1292,8 +1283,7 @@ static void pcs_map_queue_resolve(struct pcs_map_entry *
m, struct pcs_int_reque
return;
}
/* If converting a hole, adjust res_offset */
- if (direction && !m->cs_list && !(m->state & PCS_MAP_RESOLVING)
- && ireq->type == PCS_IREQ_IOCHUNK)
+ if (direction && !m->cs_list && (ireq->type == PCS_IREQ_IOCHUNK))
m->res_offset = ireq->iochunk.chunk + ireq->iochunk.offset;
m->state |= PCS_MAP_RESOLVING;
@@ -1306,8 +1296,10 @@ static void pcs_map_queue_resolve(struct pcs_map_entry *
m, struct pcs_int_reque
if (ret) {
TRACE("map error: %d for " MAP_FMT "\n", ret, MAP_ARGS(m));
spin_lock(&m->lock);
- pcs_map_truncate(m, &l);
- map_del_lru(m);
+ if (!(m->state & PCS_MAP_DEAD)) {
+ pcs_map_truncate(m, &l);
+ map_del_lru(m);
+ }
spin_unlock(&m->lock);
pcs_ireq_queue_fail(&l, PCS_ERR_NOMEM);
pcs_map_put(m);
@@ -1581,37 +1573,34 @@ static void pcs_cs_wakeup(struct pcs_cs * cs)
sreq->flags |= IREQ_F_REQUEUED;
- if (sreq->type != PCS_IREQ_FLUSH) {
- FUSE_KDTRACE(sreq->cc->fc,
- "wakeup {%p} cpu%u %d %u/%u " DENTRY_FMT "
%llu+%llu",
- sreq, smp_processor_id(),
cs->cong_queue_len,
- cs->in_flight, cs->eff_cwnd,
DENTRY_ARGS(sreq->dentry),
- sreq->iochunk.chunk + sreq->iochunk.offset,
- sreq->iochunk.size);
- map = pcs_find_get_map(sreq->dentry,
sreq->iochunk.chunk +
- ((sreq->flags &
IREQ_F_MAPPED) ? 0 : sreq->iochunk.offset));
- if (map) {
- if (sreq->iochunk.map)
- pcs_map_put(sreq->iochunk.map);
- sreq->iochunk.map = map;
- if (sreq->iochunk.flow) {
- struct pcs_int_request * preq =
sreq->completion_data.parent;
-
- pcs_flow_confirm(sreq->iochunk.flow,
&map->mapping->ftab, preq->apireq.req->type == PCS_REQ_T_WRITE,
- preq->apireq.req->pos,
preq->apireq.req->size,
- &sreq->cc->maps.ftab);
- }
- map_submit(map, sreq);
- } else {
- map_queue_on_limit(sreq);
+ if (sreq->type == PCS_IREQ_FLUSH) {
+ map = sreq->flushreq.map;
+ map_submit(map, sreq);
+ continue;
+ }
+
+ FUSE_KDTRACE(sreq->cc->fc,
+ "wakeup {%p} cpu%u %d %u/%u " DENTRY_FMT "
%llu+%llu",
+ sreq, smp_processor_id(), cs->cong_queue_len,
+ cs->in_flight, cs->eff_cwnd,
DENTRY_ARGS(sreq->dentry),
+ sreq->iochunk.chunk + sreq->iochunk.offset,
+ sreq->iochunk.size);
+ map = pcs_find_get_map(sreq->dentry, sreq->iochunk.chunk +
+ ((sreq->flags & IREQ_F_MAPPED) ? 0 :
sreq->iochunk.offset));
+ if (map) {
+ if (sreq->iochunk.map)
+ pcs_map_put(sreq->iochunk.map);
+ sreq->iochunk.map = map;
+ if (sreq->iochunk.flow) {
+ struct pcs_int_request * preq =
sreq->completion_data.parent;
+
+ pcs_flow_confirm(sreq->iochunk.flow,
&map->mapping->ftab, preq->apireq.req->type == PCS_REQ_T_WRITE,
+ preq->apireq.req->pos,
preq->apireq.req->size,
+ &sreq->cc->maps.ftab);
}
+ map_submit(map, sreq);
} else {
- map = sreq->flushreq.map;
- if (map->state & PCS_MAP_DEAD) {
- pcs_clear_error(&sreq->error);
- ireq_complete(sreq);
- } else
- map_submit(map, sreq);
+ map_queue_on_limit(sreq);
}
}
}
@@ -2474,12 +2463,20 @@ void map_submit(struct pcs_map_entry * m, struct
pcs_int_request *ireq)
if (ireq->type == PCS_IREQ_IOCHUNK && !(ireq->flags &
IREQ_F_MAPPED))
ireq->iochunk.ir.hbuf.map_version = m->version;
- if (!(m->state & (1 << direction)) || (m->state & PCS_MAP_DEAD)
||
- map_chk_stale(m)) {
+ if (m->state & PCS_MAP_DEAD) {
+ /* This should not happen unless aio_dio/fsync vs
truncate race */
+ BUG_ON(ireq->type != PCS_IREQ_FLUSH);
spin_unlock(&m->lock);
+ pcs_clear_error(&ireq->error);
+ ireq_complete(ireq);
+ return;
+ }
+
+ if (!(m->state & (1 << direction)) || map_chk_stale(m)) {
pcs_map_queue_resolve(m, ireq, direction);
return;
}
+
DTRACE("enter m: " MAP_FMT ", ireq:%p \n", MAP_ARGS(m), ireq);
csl = m->cs_list;
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel