Ack On Tue, Jan 7, 2025 at 8:56 PM Liu Kui <kui....@virtuozzo.com> wrote: > > When a read request is killed, its buff pages would have been dropped, > copying data over would cause kernel crash due to invalid memory access. > Therefore we should not copying data over to a killed request. > > Meanwhile if a read request is already under data write back IO, we > should wait for it to complete instead of killing it to avoid freeing > its buff pages. > > Related to #VSTOR-96560 > > Signed-off-by: Liu Kui <kui....@virtuozzo.com> > --- > fs/fuse/dev.c | 19 +++++++++---------- > fs/fuse/inode.c | 6 +++++- > 2 files changed, 14 insertions(+), 11 deletions(-) > > diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c > index 0fef877f731f..101bd4907828 100644 > --- a/fs/fuse/dev.c > +++ b/fs/fuse/dev.c > @@ -2017,6 +2017,9 @@ static int copy_out_splices(struct fuse_copy_state *cs, > struct fuse_args *args, > struct page *dpage = ap->pages[0]; > struct fd f = { .file = NULL }; > > + if (args->out_numargs != 1 || !args->out_pages) > + return -EINVAL; > + > nsplices = nbytes - sizeof(struct fuse_out_header); > if (nsplices & 3) > return -EINVAL; > @@ -2156,6 +2159,9 @@ static int copy_out_krpczc(struct fuse_copy_state *cs, > struct fuse_args *args, > void *dst; > int err; > > + if (args->out_numargs != 1 || !args->out_pages) > + return -EINVAL; > + > nchunks = nbytes - sizeof(struct fuse_out_header); > > /* this is always at least one chunk */ > @@ -2323,15 +2329,6 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, > goto copy_finish; > } > > - if (oh.error == FUSE_OUT_SPLICES && > - oh.error == FUSE_OUT_KRPCZC) { > - if (req->args->out_numargs != 1 || !req->args->out_pages) { > - spin_unlock(&fpq->lock); > - err = -EINVAL; > - goto copy_finish; > - } > - } > - > clear_bit(FR_SENT, &req->flags); > list_move(&req->list, &fpq->io); > req->out.h = oh; > @@ -2341,7 +2338,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, > if (!req->args->page_replace) > cs->move_pages = 0; > > - if (oh.error == FUSE_OUT_SPLICES) { > + if (req->args->killed) { > + err = -EINVAL; > + } else if (oh.error == FUSE_OUT_SPLICES) { > req->out.h.error = 0; > err = copy_out_splices(cs, req->args, nbytes); > } else if (oh.error == FUSE_OUT_KRPCZC) { > diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c > index cd0dbd74db33..d1456a5e1693 100644 > --- a/fs/fuse/inode.c > +++ b/fs/fuse/inode.c > @@ -489,6 +489,11 @@ void fuse_kill_requests(struct fuse_conn *fc, struct > inode *inode, > int i; > > BUG_ON(req->in.h.opcode != FUSE_READ); > + > + /* skip the request that is under data write back IO > */ > + if (test_bit(FR_LOCKED, &req->flags) && > req->out.h.unique) > + continue; > + > req->args->killed = 1; > > for (i = 0; i < ia->ap.num_pages; i++) { > @@ -600,7 +605,6 @@ int fuse_invalidate_files(struct fuse_conn *fc, u64 > nodeid) > fuse_kill_requests(fc, inode, > &fpq->processing[i]); > fuse_kill_requests(fc, inode, &fpq->io); > spin_unlock(&fpq->lock); > - > } > > wake_up(&fi->page_waitq); /* readpage[s] can wait on fuse wb > */ > -- > 2.39.5 (Apple Git-154)
_______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel