<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
This is a resend of previous patch however including the removal patch. Please take this version </div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Liu Kui <kui.liu@virtuozzo.com><br>
<b>Sent:</b> 06 November 2025 10:14<br>
<b>To:</b> devel@openvz.org <devel@openvz.org><br>
<b>Cc:</b> Alexey Kuznetsov <kuznet@virtuozzo.com>; Andrey Zaitsev <azaitsev@virtuozzo.com>; Konstantin Khorenko <khorenko@virtuozzo.com>; Kui Liu <kui.liu@virtuozzo.com><br>
<b>Subject:</b> [PATCH VZ9 v2 1/2] fs/fuse/kio: fix unwarranted warning due to flush request race</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">The warning in pcs_map_queue_resolve() was triggered not by an expected<br>
bug, but due to a race in processing flush requests originating from the<br>
timer.<br>
<br>
Straighten out the map resolve process flow to fix the race by avoiding<br>
repeated lock/unlock of the map lock across several functions.<br>
<br>
Additionally, promote the warning condition in pcs_map_queue_resolve() to<br>
an assertion in map_submit() to trigger a coredump if the condition truly<br>
occurs.<br>
<br>
Related to: #VSTOR-116825<br>
<a href="https://virtuozzo.atlassian.net/browse/VSTOR-116825">https://virtuozzo.atlassian.net/browse/VSTOR-116825</a><br>
<br>
Signed-off-by: Liu Kui <kui.liu@virtuozzo.com><br>
---<br>
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 11 ----<br>
fs/fuse/kio/pcs/pcs_map.c | 91 +++++++++++++++---------------<br>
2 files changed, 44 insertions(+), 58 deletions(-)<br>
<br>
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
index 5444fb8aeb05..1031c43bbec7 100644<br>
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
@@ -601,22 +601,11 @@ int fuse_map_resolve(struct pcs_map_entry *m, int direction)<br>
size_t map_sz;<br>
int err;<br>
<br>
- spin_lock(&m->lock);<br>
-<br>
- if (m->state & PCS_MAP_DEAD) {<br>
- spin_unlock(&m->lock);<br>
- pcs_map_put(m);<br>
- return 0;<br>
- }<br>
di = pcs_dentry_from_mapping(m->mapping);<br>
fm = get_fuse_mount(&di->inode->inode);<br>
<br>
DTRACE("enter m: " MAP_FMT ", dir:%d \n", MAP_ARGS(m), direction);<br>
<br>
- BUG_ON(!(m->state & PCS_MAP_RESOLVING));<br>
-<br>
- spin_unlock(&m->lock);<br>
-<br>
map_sz = sizeof(*map_ioc) + PCS_MAX_CS_CNT * sizeof(struct pcs_cs_info);<br>
map_ioc = kzalloc(map_sz, GFP_NOIO);<br>
if (!map_ioc)<br>
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c<br>
index 62b083b4947f..8baff296aaa7 100644<br>
--- a/fs/fuse/kio/pcs/pcs_map.c<br>
+++ b/fs/fuse/kio/pcs/pcs_map.c<br>
@@ -1266,23 +1266,14 @@ void pcs_map_complete(struct pcs_map_entry *m, struct pcs_ioc_getmap *omap)<br>
<br>
/* Atomically schedule map resolve and push ireq to wait completion */<br>
static void pcs_map_queue_resolve(struct pcs_map_entry * m, struct pcs_int_request *ireq, int direction)<br>
+__releases(m->lock)<br>
{<br>
LIST_HEAD(l);<br>
int ret;<br>
<br>
- DTRACE("enter m:%p, state:%x, ireq:%p dir:%d \n", m, m->state, ireq, direction);<br>
-<br>
- spin_lock(&m->lock);<br>
- /* This should not happen unless aio_dio/fsync vs truncate race */<br>
- if (m->state & PCS_MAP_DEAD) {<br>
- spin_unlock(&m->lock);<br>
+ assert_spin_locked(&m->lock);<br>
<br>
- /* If this happens, it's assumed this is a bug that needs to be fixed */<br>
- WARN_ON_ONCE(1);<br>
- list_add(&ireq->list, &l);<br>
- pcs_ireq_queue_fail(&l, PCS_ERR_NET_ABORT);<br>
- return;<br>
- }<br>
+ DTRACE("enter m:%p, state:%x, ireq:%p dir:%d \n", m, m->state, ireq, direction);<br>
DTRACE("dentry: "DENTRY_FMT, DENTRY_ARGS(pcs_dentry_from_map(m)));<br>
DTRACE("%p {%p %p}\n",ireq, ireq->list.next, ireq->list.prev);<br>
BUG_ON(!list_empty(&ireq->list));<br>
@@ -1293,8 +1284,7 @@ static void pcs_map_queue_resolve(struct pcs_map_entry * m, struct pcs_int_reque<br>
return;<br>
}<br>
/* If converting a hole, adjust res_offset */<br>
- if (direction && !m->cs_list && !(m->state & PCS_MAP_RESOLVING)<br>
- && ireq->type == PCS_IREQ_IOCHUNK)<br>
+ if (direction && !m->cs_list && (ireq->type == PCS_IREQ_IOCHUNK))<br>
m->res_offset = ireq->iochunk.chunk + ireq->iochunk.offset;<br>
<br>
m->state |= PCS_MAP_RESOLVING;<br>
@@ -1307,8 +1297,10 @@ static void pcs_map_queue_resolve(struct pcs_map_entry * m, struct pcs_int_reque<br>
if (ret) {<br>
TRACE("map error: %d for " MAP_FMT "\n", ret, MAP_ARGS(m));<br>
spin_lock(&m->lock);<br>
- pcs_map_truncate(m, &l);<br>
- map_del_lru(m);<br>
+ if (!(m->state & PCS_MAP_DEAD)) {<br>
+ pcs_map_truncate(m, &l);<br>
+ map_del_lru(m);<br>
+ }<br>
spin_unlock(&m->lock);<br>
pcs_ireq_queue_fail(&l, PCS_ERR_NOMEM);<br>
pcs_map_put(m);<br>
@@ -1582,37 +1574,34 @@ static void pcs_cs_wakeup(struct pcs_cs * cs)<br>
<br>
sreq->flags |= IREQ_F_REQUEUED;<br>
<br>
- if (sreq->type != PCS_IREQ_FLUSH) {<br>
- FUSE_KDTRACE(sreq->cc->fc,<br>
- "wakeup {%p} cpu%u %d %u/%u " DENTRY_FMT " %llu+%llu",<br>
- sreq, smp_processor_id(), cs->cong_queue_len,<br>
- cs->in_flight, cs->eff_cwnd, DENTRY_ARGS(sreq->dentry),<br>
- sreq->iochunk.chunk + sreq->iochunk.offset,<br>
- sreq->iochunk.size);<br>
- map = pcs_find_get_map(sreq->dentry, sreq->iochunk.chunk +<br>
- ((sreq->flags & IREQ_F_MAPPED) ? 0 : sreq->iochunk.offset));<br>
- if (map) {<br>
- if (sreq->iochunk.map)<br>
- pcs_map_put(sreq->iochunk.map);<br>
- sreq->iochunk.map = map;<br>
- if (sreq->iochunk.flow) {<br>
- struct pcs_int_request * preq = sreq->completion_data.parent;<br>
-<br>
- pcs_flow_confirm(sreq->iochunk.flow, &map->mapping->ftab, preq->apireq.req->type == PCS_REQ_T_WRITE,<br>
- preq->apireq.req->pos, preq->apireq.req->size,<br>
- &sreq->cc->maps.ftab);<br>
- }<br>
- map_submit(map, sreq);<br>
- } else {<br>
- map_queue_on_limit(sreq);<br>
+ if (sreq->type == PCS_IREQ_FLUSH) {<br>
+ map = sreq->flushreq.map;<br>
+ map_submit(map, sreq);<br>
+ continue;<br>
+ }<br>
+<br>
+ FUSE_KDTRACE(sreq->cc->fc,<br>
+ "wakeup {%p} cpu%u %d %u/%u " DENTRY_FMT " %llu+%llu",<br>
+ sreq, smp_processor_id(), cs->cong_queue_len,<br>
+ cs->in_flight, cs->eff_cwnd, DENTRY_ARGS(sreq->dentry),<br>
+ sreq->iochunk.chunk + sreq->iochunk.offset,<br>
+ sreq->iochunk.size);<br>
+ map = pcs_find_get_map(sreq->dentry, sreq->iochunk.chunk +<br>
+ ((sreq->flags & IREQ_F_MAPPED) ? 0 : sreq->iochunk.offset));<br>
+ if (map) {<br>
+ if (sreq->iochunk.map)<br>
+ pcs_map_put(sreq->iochunk.map);<br>
+ sreq->iochunk.map = map;<br>
+ if (sreq->iochunk.flow) {<br>
+ struct pcs_int_request * preq = sreq->completion_data.parent;<br>
+<br>
+ pcs_flow_confirm(sreq->iochunk.flow, &map->mapping->ftab, preq->apireq.req->type == PCS_REQ_T_WRITE,<br>
+ preq->apireq.req->pos, preq->apireq.req->size,<br>
+ &sreq->cc->maps.ftab);<br>
}<br>
+ map_submit(map, sreq);<br>
} else {<br>
- map = sreq->flushreq.map;<br>
- if (map->state & PCS_MAP_DEAD) {<br>
- pcs_clear_error(&sreq->error);<br>
- ireq_complete(sreq);<br>
- } else<br>
- map_submit(map, sreq);<br>
+ map_queue_on_limit(sreq);<br>
}<br>
}<br>
}<br>
@@ -2474,12 +2463,20 @@ void map_submit(struct pcs_map_entry * m, struct pcs_int_request *ireq)<br>
if (ireq->type == PCS_IREQ_IOCHUNK && !(ireq->flags & IREQ_F_MAPPED))<br>
ireq->iochunk.hbuf.map_version = m->version;<br>
<br>
- if (!(m->state & (1 << direction)) || (m->state & PCS_MAP_DEAD) ||<br>
- map_chk_stale(m)) {<br>
+ if (m->state & PCS_MAP_DEAD) {<br>
+ /* This should not happen unless aio_dio/fsync vs truncate race */<br>
+ BUG_ON(ireq->type != PCS_IREQ_FLUSH);<br>
spin_unlock(&m->lock);<br>
+ pcs_clear_error(&ireq->error);<br>
+ ireq_complete(ireq);<br>
+ return;<br>
+ }<br>
+<br>
+ if (!(m->state & (1 << direction)) || map_chk_stale(m)) {<br>
pcs_map_queue_resolve(m, ireq, direction);<br>
return;<br>
}<br>
+<br>
DTRACE("enter m: " MAP_FMT ", ireq:%p \n", MAP_ARGS(m), ireq);<br>
<br>
csl = m->cs_list;<br>
-- <br>
2.39.5 (Apple Git-154)<br>
<br>
</div>
</span></font></div>
</body>
</html>