hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/fs/fuse/virtio_fs.c
....@@ -18,6 +18,12 @@
1818 #include <linux/uio.h>
1919 #include "fuse_i.h"
2020
21
+/* Used to help calculate the FUSE connection's max_pages limit for a request's
22
+ * size. Parts of the struct fuse_req are sliced into scattergather lists in
23
+ * addition to the pages used, so this can help account for that overhead.
24
+ */
25
+#define FUSE_HEADER_OVERHEAD 4
26
+
2127 /* List of virtio-fs device instances and a lock for the list. Also provides
2228 * mutual exclusion in device removal and mounting path
2329 */
....@@ -1395,7 +1401,7 @@
13951401 bool last;
13961402
13971403 /* If mount failed, we can still be called without any fc */
1398
- if (fm) {
1404
+ if (sb->s_root) {
13991405 last = fuse_mount_remove(fm);
14001406 if (last)
14011407 virtio_fs_conn_destroy(fm);
....@@ -1428,9 +1434,10 @@
14281434 {
14291435 struct virtio_fs *fs;
14301436 struct super_block *sb;
1431
- struct fuse_conn *fc;
1437
+ struct fuse_conn *fc = NULL;
14321438 struct fuse_mount *fm;
1433
- int err;
1439
+ unsigned int virtqueue_size;
1440
+ int err = -EIO;
14341441
14351442 /* This gets a reference on virtio_fs object. This ptr gets installed
14361443 * in fc->iq->priv. Once fuse_conn is going away, it calls ->put()
....@@ -1442,27 +1449,27 @@
14421449 return -EINVAL;
14431450 }
14441451
1452
+ virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq);
1453
+ if (WARN_ON(virtqueue_size <= FUSE_HEADER_OVERHEAD))
1454
+ goto out_err;
1455
+
1456
+ err = -ENOMEM;
14451457 fc = kzalloc(sizeof(struct fuse_conn), GFP_KERNEL);
1446
- if (!fc) {
1447
- mutex_lock(&virtio_fs_mutex);
1448
- virtio_fs_put(fs);
1449
- mutex_unlock(&virtio_fs_mutex);
1450
- return -ENOMEM;
1451
- }
1458
+ if (!fc)
1459
+ goto out_err;
14521460
14531461 fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL);
1454
- if (!fm) {
1455
- mutex_lock(&virtio_fs_mutex);
1456
- virtio_fs_put(fs);
1457
- mutex_unlock(&virtio_fs_mutex);
1458
- kfree(fc);
1459
- return -ENOMEM;
1460
- }
1462
+ if (!fm)
1463
+ goto out_err;
14611464
14621465 fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs);
14631466 fc->release = fuse_free_conn;
14641467 fc->delete_stale = true;
14651468 fc->auto_submounts = true;
1469
+
1470
+ /* Tell FUSE to split requests that exceed the virtqueue's size */
1471
+ fc->max_pages_limit = min_t(unsigned int, fc->max_pages_limit,
1472
+ virtqueue_size - FUSE_HEADER_OVERHEAD);
14661473
14671474 fsc->s_fs_info = fm;
14681475 sb = sget_fc(fsc, virtio_fs_test_super, virtio_fs_set_super);
....@@ -1485,6 +1492,13 @@
14851492 WARN_ON(fsc->root);
14861493 fsc->root = dget(sb->s_root);
14871494 return 0;
1495
+
1496
+out_err:
1497
+ kfree(fc);
1498
+ mutex_lock(&virtio_fs_mutex);
1499
+ virtio_fs_put(fs);
1500
+ mutex_unlock(&virtio_fs_mutex);
1501
+ return err;
14881502 }
14891503
14901504 static const struct fs_context_operations virtio_fs_context_ops = {