.. | .. |
---|
18 | 18 | #include <linux/uio.h> |
---|
19 | 19 | #include "fuse_i.h" |
---|
20 | 20 | |
---|
| 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 | + |
---|
21 | 27 | /* List of virtio-fs device instances and a lock for the list. Also provides |
---|
22 | 28 | * mutual exclusion in device removal and mounting path |
---|
23 | 29 | */ |
---|
.. | .. |
---|
1395 | 1401 | bool last; |
---|
1396 | 1402 | |
---|
1397 | 1403 | /* If mount failed, we can still be called without any fc */ |
---|
1398 | | - if (fm) { |
---|
| 1404 | + if (sb->s_root) { |
---|
1399 | 1405 | last = fuse_mount_remove(fm); |
---|
1400 | 1406 | if (last) |
---|
1401 | 1407 | virtio_fs_conn_destroy(fm); |
---|
.. | .. |
---|
1428 | 1434 | { |
---|
1429 | 1435 | struct virtio_fs *fs; |
---|
1430 | 1436 | struct super_block *sb; |
---|
1431 | | - struct fuse_conn *fc; |
---|
| 1437 | + struct fuse_conn *fc = NULL; |
---|
1432 | 1438 | struct fuse_mount *fm; |
---|
1433 | | - int err; |
---|
| 1439 | + unsigned int virtqueue_size; |
---|
| 1440 | + int err = -EIO; |
---|
1434 | 1441 | |
---|
1435 | 1442 | /* This gets a reference on virtio_fs object. This ptr gets installed |
---|
1436 | 1443 | * in fc->iq->priv. Once fuse_conn is going away, it calls ->put() |
---|
.. | .. |
---|
1442 | 1449 | return -EINVAL; |
---|
1443 | 1450 | } |
---|
1444 | 1451 | |
---|
| 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; |
---|
1445 | 1457 | 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; |
---|
1452 | 1460 | |
---|
1453 | 1461 | 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; |
---|
1461 | 1464 | |
---|
1462 | 1465 | fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs); |
---|
1463 | 1466 | fc->release = fuse_free_conn; |
---|
1464 | 1467 | fc->delete_stale = true; |
---|
1465 | 1468 | 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); |
---|
1466 | 1473 | |
---|
1467 | 1474 | fsc->s_fs_info = fm; |
---|
1468 | 1475 | sb = sget_fc(fsc, virtio_fs_test_super, virtio_fs_set_super); |
---|
.. | .. |
---|
1485 | 1492 | WARN_ON(fsc->root); |
---|
1486 | 1493 | fsc->root = dget(sb->s_root); |
---|
1487 | 1494 | 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; |
---|
1488 | 1502 | } |
---|
1489 | 1503 | |
---|
1490 | 1504 | static const struct fs_context_operations virtio_fs_context_ops = { |
---|