Variable parent_N shared between states was put to data private to one particular state and overwritten while state switches.
The core reason for this sad mistake was aliasing between anonymous union member and the same member looking like it is common. It was obvious this is a way to trouble, but desire to minimize patch size was overwhelming. Fix this. Affects: #VSTOR-109945 Signed-off-by: Alexey Kuznetsov <[email protected]> --- fs/fuse/kio/pcs/pcs_cluster.c | 8 ++++---- fs/fuse/kio/pcs/pcs_cs.c | 18 +++++++++--------- fs/fuse/kio/pcs/pcs_cs_accel.c | 12 ++++++------ fs/fuse/kio/pcs/pcs_map.c | 10 +++++----- fs/fuse/kio/pcs/pcs_req.h | 12 ++---------- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/fs/fuse/kio/pcs/pcs_cluster.c b/fs/fuse/kio/pcs/pcs_cluster.c index 710087c..c475d04 100644 --- a/fs/fuse/kio/pcs/pcs_cluster.c +++ b/fs/fuse/kio/pcs/pcs_cluster.c @@ -245,8 +245,8 @@ static void fiemap_process_one(struct fiemap_iterator *fiter) fiter->apireq.size = sreq->iochunk.size = DENTRY_CHUNK_SIZE(di) - sreq->iochunk.offset; sreq->iochunk.csl = NULL; sreq->iochunk.banned_cs.val = 0; - sreq->iochunk.msg.destructor = NULL; - sreq->iochunk.msg.rpc = NULL; + sreq->iochunk.ir.msg.destructor = NULL; + sreq->iochunk.ir.msg.rpc = NULL; pcs_sreq_attach(sreq, &fiter->ireq); sreq->complete_cb = pcs_sreq_complete; @@ -403,8 +403,8 @@ static noinline void __pcs_cc_process_ireq_rw(struct pcs_int_request *ireq) sreq->iochunk.size = len; sreq->iochunk.csl = NULL; sreq->iochunk.banned_cs.val = 0; - sreq->iochunk.msg.destructor = NULL; - sreq->iochunk.msg.rpc = NULL; + sreq->iochunk.ir.msg.destructor = NULL; + sreq->iochunk.ir.msg.rpc = NULL; pcs_sreq_attach(sreq, ireq); sreq->complete_cb = pcs_sreq_complete; diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c index 8c1fdce..53bd520 100644 --- a/fs/fuse/kio/pcs/pcs_cs.c +++ b/fs/fuse/kio/pcs/pcs_cs.c @@ -381,7 +381,7 @@ static void cs_response_done(struct pcs_msg *msg) pcs_map_verify_sync_state(ireq->dentry, ireq, msg); } else { FUSE_KTRACE(ireq->cc->fc, XID_FMT " IO error %d %lu, ireq:%p : %llu:%u+%u", - XID_ARGS(ireq->iochunk.hbuf.hdr.xid), msg->error.value, + XID_ARGS(ireq->iochunk.ir.hbuf.hdr.xid), msg->error.value, msg->error.remote ? (unsigned long)msg->error.offender.val : 0UL, ireq, (unsigned long long)ireq->iochunk.chunk, (unsigned)ireq->iochunk.offset, @@ -488,9 +488,10 @@ static void cs_get_data(struct pcs_msg *msg, int offset, struct iov_iter *it, un struct pcs_int_request *ireq = ireq_from_msg(msg); if (offset < sizeof(struct pcs_cs_iohdr)) { - ireq->iochunk.hbuf_kv.iov_base = &ireq->iochunk.hbuf; - ireq->iochunk.hbuf_kv.iov_len = sizeof(struct pcs_cs_iohdr); - iov_iter_kvec(it, direction, &ireq->iochunk.hbuf_kv, 1, sizeof(struct pcs_cs_iohdr)); + ireq->iochunk.ir.hbuf_kv.iov_base = &ireq->iochunk.ir.hbuf; + ireq->iochunk.ir.hbuf_kv.iov_len = sizeof(struct pcs_cs_iohdr); + iov_iter_kvec(it, direction, &ireq->iochunk.ir.hbuf_kv, 1, + sizeof(struct pcs_cs_iohdr)); iov_iter_advance(it, offset); TRACE("return msg:%p->size:%d off:%d it_len:%ld\n", msg, msg->size, offset, iov_iter_count(it)); @@ -624,8 +624,8 @@ static void ireq_complete_fo(struct pcs_int_request * ireq) } FUSE_TRACE_COMMIT(fc->ktrace); } - ireq->iochunk.msg.destructor = NULL; - ireq->iochunk.msg.rpc = NULL; + ireq->iochunk.ir.msg.destructor = NULL; + ireq->iochunk.ir.msg.rpc = NULL; ireq_complete(ireq); } @@ -653,7 +653,7 @@ static void complete_fo_request(struct pcs_int_request * sreq) static void do_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq) { - struct pcs_msg *msg = &ireq->iochunk.msg; + struct pcs_msg *msg = &ireq->iochunk.ir.msg; struct pcs_cs_iohdr *ioh; struct pcs_cs_list *csl = ireq->iochunk.csl; struct pcs_map_entry *map = ireq->iochunk.map; /* ireq keeps reference to map */ @@ -665,7 +665,7 @@ static void do_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq) msg->private = cs; msg->private2 = ireq; - ioh = &ireq->iochunk.hbuf; + ioh = &ireq->iochunk.ir.hbuf; ioh->hdr.len = pcs_cs_msg_size(sizeof(struct pcs_cs_iohdr), storage_version); aligned_msg = pcs_cs_use_aligned_io(storage_version); @@ -741,7 +741,7 @@ static void do_cs_submit(struct pcs_cs *cs, struct pcs_int_request *ireq) DTRACE(XID_FMT " About to send msg:%p, ireq:%p, cmd:%u," " id:"CUID_FMT" v:"VER_FMT" - %llu:%u+%u\n", - XID_ARGS(ireq->iochunk.hbuf.hdr.xid), msg, ireq, + XID_ARGS(ireq->iochunk.ir.hbuf.hdr.xid), msg, ireq, ireq->iochunk.cmd, CUID_ARGS(ioh->uid), VER_ARGS(ioh->map_version), (unsigned long long)ireq->iochunk.chunk, diff --git a/fs/fuse/kio/pcs/pcs_cs_accel.c b/fs/fuse/kio/pcs/pcs_cs_accel.c index 036ca17..ef30ac8 100644 --- a/fs/fuse/kio/pcs/pcs_cs_accel.c +++ b/fs/fuse/kio/pcs/pcs_cs_accel.c @@ -510,8 +510,8 @@ static void __pcs_csa_final_completion(struct pcs_aio_req *areq) /* Prepare ireq for restart in slow path */ ireq->flags |= IREQ_F_NO_ACCEL|IREQ_F_ACCELERROR; ireq->flags &= ~IREQ_F_ONCE; - ireq->iochunk.msg.destructor = NULL; - ireq->iochunk.msg.rpc = NULL; + ireq->iochunk.ir.msg.destructor = NULL; + ireq->iochunk.ir.msg.rpc = NULL; } out: @@ -954,8 +954,8 @@ int pcs_csa_cs_submit(struct pcs_cs * cs, struct pcs_int_request * ireq) return 1; rcu_read_lock(); /* Clear state which could be rewritten by csa_submit */ - ireq->iochunk.msg.destructor = NULL; - ireq->iochunk.msg.rpc = NULL; + ireq->iochunk.ir.msg.destructor = NULL; + ireq->iochunk.ir.msg.rpc = NULL; ireq->flags |= IREQ_F_NO_ACCEL; } } @@ -1041,8 +1041,8 @@ static void ireq_clear_acr(struct pcs_int_request * ireq) ireq->iochunk.acr.awr[i].bvec_copy = NULL; } } - ireq->iochunk.msg.destructor = NULL; - ireq->iochunk.msg.rpc = NULL; + ireq->iochunk.ir.msg.destructor = NULL; + ireq->iochunk.ir.msg.rpc = NULL; ireq->flags |= IREQ_F_NO_ACCEL; } diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c index 62b083b..2d95dc2 100644 --- a/fs/fuse/kio/pcs/pcs_map.c +++ b/fs/fuse/kio/pcs/pcs_map.c @@ -1371,7 +1371,7 @@ void map_notify_iochunk_error(struct pcs_int_request * sreq) if (!m || (m->state & PCS_MAP_DEAD)) return; - map_notify_error(m, sreq, &sreq->iochunk.hbuf.map_version, sreq->iochunk.csl); + map_notify_error(m, sreq, &sreq->iochunk.ir.hbuf.map_version, sreq->iochunk.csl); } static void map_replicating(struct pcs_int_request *ireq) @@ -1770,7 +1770,8 @@ void map_notify_soft_error(struct pcs_int_request *ireq) if (pcs_if_error(&ireq->error)) map_notify_iochunk_error(ireq); - if (map_version_compare(&ireq->iochunk.hbuf.map_version, &ireq->iochunk.map->version) < 0) + if (map_version_compare(&ireq->iochunk.ir.hbuf.map_version, + &ireq->iochunk.map->version) < 0) ireq->flags &= ~IREQ_F_ONCE; pcs_deaccount_ireq(ireq, &err); @@ -1973,8 +1973,8 @@ struct pcs_int_request * sreq->iochunk.csl = NULL; sreq->iochunk.banned_cs.val = 0; sreq->complete_cb = ireq->complete_cb; - sreq->iochunk.msg.destructor = NULL; - sreq->iochunk.msg.rpc = NULL; + sreq->iochunk.ir.msg.destructor = NULL; + sreq->iochunk.ir.msg.rpc = NULL; pcs_sreq_attach(sreq, ireq->completion_data.parent); ireq->iochunk.size -= iochunk; @@ -2472,7 +2472,7 @@ void map_submit(struct pcs_map_entry * m, struct pcs_int_request *ireq) spin_lock(&m->lock); if (ireq->type == PCS_IREQ_IOCHUNK && !(ireq->flags & IREQ_F_MAPPED)) - ireq->iochunk.hbuf.map_version = m->version; + ireq->iochunk.ir.hbuf.map_version = m->version; if (!(m->state & (1 << direction)) || (m->state & PCS_MAP_DEAD) || map_chk_stale(m)) { diff --git a/fs/fuse/kio/pcs/pcs_req.h b/fs/fuse/kio/pcs/pcs_req.h index 94fcfdb..61d3575 100644 --- a/fs/fuse/kio/pcs/pcs_req.h +++ b/fs/fuse/kio/pcs/pcs_req.h @@ -93,7 +93,6 @@ struct pcs_iochunk_req { * A little ugly */ struct kvec hbuf_kv; - struct pcs_int_request *parent_N; }; struct pcs_fo_req @@ -183,15 +182,8 @@ struct pcs_int_request u64 offset; struct pcs_cs_list *csl; PCS_NODE_ID_T banned_cs; + struct pcs_int_request *parent_N; union { - struct { - struct pcs_msg msg; - struct pcs_cs_iohdr hbuf; /* Buffer for header. - * A little ugly - */ - struct kvec hbuf_kv; - struct pcs_int_request *parent_N; - }; struct pcs_iochunk_req ir; struct pcs_fo_req fo; struct pcs_aio_req ar; @@ -383,7 +375,7 @@ static inline int pcs_sreq_detach(struct pcs_int_request * sreq) static inline struct pcs_int_request *ireq_from_msg(struct pcs_msg *msg) { - return container_of(msg, struct pcs_int_request, iochunk.msg); + return container_of(msg, struct pcs_int_request, iochunk.ir.msg); } static inline void ireq_process(struct pcs_int_request *ireq) -- 1.8.3.1 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
