Acknowledged

On Wed, Oct 15, 2025 at 7:11 PM Liu Kui <[email protected]> wrote:
>
> 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.
>
> Related to: #VSTOR-116825
> https://virtuozzo.atlassian.net/browse/VSTOR-116825
>
> Signed-off-by: Liu Kui <[email protected]>
> ---
>  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 5444fb8aeb05..1031c43bbec7 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 62b083b4947f..8baff296aaa7 100644
> --- a/fs/fuse/kio/pcs/pcs_map.c
> +++ b/fs/fuse/kio/pcs/pcs_map.c
> @@ -1266,23 +1266,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));
> @@ -1293,8 +1284,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;
> @@ -1307,8 +1297,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);
> @@ -1582,37 +1574,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.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;
> --
> 2.39.5 (Apple Git-154)

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to