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