diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 86c4b63f795c..cb3b992f9fe5 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -996,7 +996,17 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, while (count) { if (cs->write && cs->pipebufs && page) { - return fuse_ref_page(cs, page, offset, count); + /* + * Can't control lifetime of pipe buffers, so always + * copy user pages. + */ + if (cs->req->user_pages) { + err = fuse_copy_fill(cs); + if (err) + return err; + } else { + return fuse_ref_page(cs, page, offset, count); + } } else if (!cs->len) { if (cs->move_pages && page && offset == 0 && count == PAGE_SIZE) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 5ab9a70e2367..84322766ca7d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1319,6 +1319,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii, (PAGE_SIZE - ret) & (PAGE_SIZE - 1); } + req->user_pages = true; if (write) req->in.argpages = 1; else diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 95d7b8282dfc..16e2c055442e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -310,6 +310,8 @@ struct fuse_req { /** refcount */ atomic_t count; + bool user_pages; + /** Unique ID for the interrupt request */ u64 intr_unique;