It is a shame. The bug is stupid and effect is disasterous. https://pmc.acronis.work/browse/VSTOR-84977
Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com> --- fs/fuse/kio/pcs/pcs_cs_accel.c | 43 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/fs/fuse/kio/pcs/pcs_cs_accel.c b/fs/fuse/kio/pcs/pcs_cs_accel.c index a18069f..9be94a6 100644 --- a/fs/fuse/kio/pcs/pcs_cs_accel.c +++ b/fs/fuse/kio/pcs/pcs_cs_accel.c @@ -932,7 +932,8 @@ static int init_crypted_data(struct pcs_int_request * ireq, int idx) struct pcs_int_request *parent = ireq->completion_data.parent; struct pcs_fuse_req * r; struct bio_vec * bvec; - int n, nvec; + int n, nvec, first; + unsigned int off, start_off, end_off; u64 pos; u64 chunk_id; struct pcs_csa_context * csa_ctx; @@ -951,14 +952,38 @@ static int init_crypted_data(struct pcs_int_request * ireq, int idx) if (!bvec) return -ENOMEM; - for (n = 0; n < nvec; n++) { - bvec[n] = r->exec.io.bvec[n]; - if ((bvec[n].bv_offset|bvec[n].bv_len)&511) + off = 0; + start_off = ireq->iochunk.dio_offset; + end_off = start_off + ireq->iochunk.size; + + for (first = 0; first < nvec; first++) { + struct bio_vec *v = r->exec.io.bvec + first; + unsigned int next = off + v->bv_len; + + if (next > start_off) + break; + off = next; + } + + for (n = 0; n < nvec - first && off < end_off; n++) { + struct bio_vec *v = r->exec.io.bvec + first + n; + unsigned int next = off + v->bv_len; + + bvec[n] = *v; + if (off < start_off) { + bvec[n].bv_offset += start_off - off; + bvec[n].bv_len -= start_off - off; + } + if (next > end_off) + bvec[n].bv_len -= next - end_off; + if ((bvec[n].bv_offset | bvec[n].bv_len) & 511) goto out; bvec[n].bv_page = alloc_page(GFP_NOIO); if (!bvec[n].bv_page) goto out; + off = next; } + nvec = n; rcu_read_lock(); csa_ctx = rcu_dereference(ireq->iochunk.csl->cs[idx].cslink.cs->csa_ctx); @@ -969,17 +994,19 @@ static int init_crypted_data(struct pcs_int_request * ireq, int idx) pos = ireq->iochunk.offset; chunk_id = ireq->iochunk.map->id; - for (n = 0; n < nvec; n++) { + for (n = 0; n < nvec; n++, first++) { if (tfm->base.base.__crt_alg->cra_priority == 400) - encrypt_page_ctr(tfm, bvec[n].bv_page, r->exec.io.bvec[n].bv_page, bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id); + encrypt_page_ctr(tfm, bvec[n].bv_page, r->exec.io.bvec[first].bv_page, + bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id); else - encrypt_page_xts(tfm, bvec[n].bv_page, r->exec.io.bvec[n].bv_page, bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id); + encrypt_page_xts(tfm, bvec[n].bv_page, r->exec.io.bvec[first].bv_page, + bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id); pos += bvec[n].bv_len; } rcu_read_unlock(); ireq->iochunk.acr.awr[idx].bvec_copy = bvec; - ireq->iochunk.acr.awr[idx].num_copy_bvecs = n; + ireq->iochunk.acr.awr[idx].num_copy_bvecs = nvec; return 0; out: -- 1.8.3.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel