From: Greg Kroah-Hartman Date: Tue, 18 Apr 2023 10:32:33 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v4.14.313~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14cf73a116a99c0f1d02d7b24cbf5dd0ef026a46;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: virtiofs-clean-up-error-handling-in-virtio_fs_get_tree.patch virtiofs-split-requests-that-exceed-virtqueue-size.patch --- diff --git a/queue-5.10/series b/queue-5.10/series index 24702d5c946..7265cc859b8 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -121,3 +121,5 @@ riscv-handle-zicsr-zifencei-issues-between-clang-and-binutils.patch kexec-move-locking-into-do_kexec_load.patch kexec-turn-all-kexec_mutex-acquisitions-into-trylocks.patch panic-kexec-make-__crash_kexec-nmi-safe.patch +virtiofs-clean-up-error-handling-in-virtio_fs_get_tree.patch +virtiofs-split-requests-that-exceed-virtqueue-size.patch diff --git a/queue-5.10/virtiofs-clean-up-error-handling-in-virtio_fs_get_tree.patch b/queue-5.10/virtiofs-clean-up-error-handling-in-virtio_fs_get_tree.patch new file mode 100644 index 00000000000..91bb32ba7c6 --- /dev/null +++ b/queue-5.10/virtiofs-clean-up-error-handling-in-virtio_fs_get_tree.patch @@ -0,0 +1,62 @@ +From 833c5a42e28beeefa1f9bd476a63fe8050c1e8ca Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 11 Nov 2020 17:22:32 +0100 +Subject: virtiofs: clean up error handling in virtio_fs_get_tree() + +From: Miklos Szeredi + +commit 833c5a42e28beeefa1f9bd476a63fe8050c1e8ca upstream. + +Avoid duplicating error cleanup. + +Signed-off-by: Miklos Szeredi +Signed-off-by: Yang Bo +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/virtio_fs.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +--- a/fs/fuse/virtio_fs.c ++++ b/fs/fuse/virtio_fs.c +@@ -1440,22 +1440,14 @@ static int virtio_fs_get_tree(struct fs_ + return -EINVAL; + } + ++ err = -ENOMEM; + fc = kzalloc(sizeof(struct fuse_conn), GFP_KERNEL); +- if (!fc) { +- mutex_lock(&virtio_fs_mutex); +- virtio_fs_put(fs); +- mutex_unlock(&virtio_fs_mutex); +- return -ENOMEM; +- } ++ if (!fc) ++ goto out_err; + + fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL); +- if (!fm) { +- mutex_lock(&virtio_fs_mutex); +- virtio_fs_put(fs); +- mutex_unlock(&virtio_fs_mutex); +- kfree(fc); +- return -ENOMEM; +- } ++ if (!fm) ++ goto out_err; + + fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs); + fc->release = fuse_free_conn; +@@ -1483,6 +1475,13 @@ static int virtio_fs_get_tree(struct fs_ + WARN_ON(fsc->root); + fsc->root = dget(sb->s_root); + return 0; ++ ++out_err: ++ kfree(fc); ++ mutex_lock(&virtio_fs_mutex); ++ virtio_fs_put(fs); ++ mutex_unlock(&virtio_fs_mutex); ++ return err; + } + + static const struct fs_context_operations virtio_fs_context_ops = { diff --git a/queue-5.10/virtiofs-split-requests-that-exceed-virtqueue-size.patch b/queue-5.10/virtiofs-split-requests-that-exceed-virtqueue-size.patch new file mode 100644 index 00000000000..0516ee001bd --- /dev/null +++ b/queue-5.10/virtiofs-split-requests-that-exceed-virtqueue-size.patch @@ -0,0 +1,122 @@ +From a7f0d7aab0b4f3f0780b1f77356e2fe7202ac0cb Mon Sep 17 00:00:00 2001 +From: Connor Kuehl +Date: Thu, 18 Mar 2021 08:52:22 -0500 +Subject: virtiofs: split requests that exceed virtqueue size + +From: Connor Kuehl + +commit a7f0d7aab0b4f3f0780b1f77356e2fe7202ac0cb upstream. + +If an incoming FUSE request can't fit on the virtqueue, the request is +placed onto a workqueue so a worker can try to resubmit it later where +there will (hopefully) be space for it next time. + +This is fine for requests that aren't larger than a virtqueue's maximum +capacity. However, if a request's size exceeds the maximum capacity of the +virtqueue (even if the virtqueue is empty), it will be doomed to a life of +being placed on the workqueue, removed, discovered it won't fit, and placed +on the workqueue yet again. + +Furthermore, from section 2.6.5.3.1 (Driver Requirements: Indirect +Descriptors) of the virtio spec: + + "A driver MUST NOT create a descriptor chain longer than the Queue + Size of the device." + +To fix this, limit the number of pages FUSE will use for an overall +request. This way, each request can realistically fit on the virtqueue +when it is decomposed into a scattergather list and avoid violating section +2.6.5.3.1 of the virtio spec. + +Signed-off-by: Connor Kuehl +Reviewed-by: Vivek Goyal +Signed-off-by: Miklos Szeredi +Signed-off-by: Yang Bo +Signed-off-by: Greg Kroah-Hartman +--- + fs/fuse/fuse_i.h | 3 +++ + fs/fuse/inode.c | 3 ++- + fs/fuse/virtio_fs.c | 19 +++++++++++++++++-- + 3 files changed, 22 insertions(+), 3 deletions(-) + +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -556,6 +556,9 @@ struct fuse_conn { + /** Maxmum number of pages that can be used in a single request */ + unsigned int max_pages; + ++ /** Constrain ->max_pages to this value during feature negotiation */ ++ unsigned int max_pages_limit; ++ + /** Input queue */ + struct fuse_iqueue iq; + +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -710,6 +710,7 @@ void fuse_conn_init(struct fuse_conn *fc + fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); + fc->user_ns = get_user_ns(user_ns); + fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; ++ fc->max_pages_limit = FUSE_MAX_MAX_PAGES; + + INIT_LIST_HEAD(&fc->mounts); + list_add(&fm->fc_entry, &fc->mounts); +@@ -1056,7 +1057,7 @@ static void process_init_reply(struct fu + fc->abort_err = 1; + if (arg->flags & FUSE_MAX_PAGES) { + fc->max_pages = +- min_t(unsigned int, FUSE_MAX_MAX_PAGES, ++ min_t(unsigned int, fc->max_pages_limit, + max_t(unsigned int, arg->max_pages, 1)); + } + if (IS_ENABLED(CONFIG_FUSE_DAX) && +--- a/fs/fuse/virtio_fs.c ++++ b/fs/fuse/virtio_fs.c +@@ -18,6 +18,12 @@ + #include + #include "fuse_i.h" + ++/* Used to help calculate the FUSE connection's max_pages limit for a request's ++ * size. Parts of the struct fuse_req are sliced into scattergather lists in ++ * addition to the pages used, so this can help account for that overhead. ++ */ ++#define FUSE_HEADER_OVERHEAD 4 ++ + /* List of virtio-fs device instances and a lock for the list. Also provides + * mutual exclusion in device removal and mounting path + */ +@@ -1426,9 +1432,10 @@ static int virtio_fs_get_tree(struct fs_ + { + struct virtio_fs *fs; + struct super_block *sb; +- struct fuse_conn *fc; ++ struct fuse_conn *fc = NULL; + struct fuse_mount *fm; +- int err; ++ unsigned int virtqueue_size; ++ int err = -EIO; + + /* This gets a reference on virtio_fs object. This ptr gets installed + * in fc->iq->priv. Once fuse_conn is going away, it calls ->put() +@@ -1440,6 +1447,10 @@ static int virtio_fs_get_tree(struct fs_ + return -EINVAL; + } + ++ virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq); ++ if (WARN_ON(virtqueue_size <= FUSE_HEADER_OVERHEAD)) ++ goto out_err; ++ + err = -ENOMEM; + fc = kzalloc(sizeof(struct fuse_conn), GFP_KERNEL); + if (!fc) +@@ -1454,6 +1465,10 @@ static int virtio_fs_get_tree(struct fs_ + fc->delete_stale = true; + fc->auto_submounts = true; + ++ /* Tell FUSE to split requests that exceed the virtqueue's size */ ++ fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit, ++ virtqueue_size - FUSE_HEADER_OVERHEAD); ++ + fsc->s_fs_info = fm; + sb = sget_fc(fsc, virtio_fs_test_super, virtio_fs_set_super); + fuse_mount_put(fm);