@samitouri / QOSamiQemu / commits / e6116a81f0

hw/9pfs: add max_xattr option

Previous patch introduced a limit of max. 1024 simultaneous xattr FIDs. This patch introduces an option "max_attr" that allows to override this limit, just for the case that some user might run into this limit for some reason, even if unlikely; or for reducing the limit further down (e.g. that default limit of 1024 would cap at max. 64 MiB host memory, at least on Linux hosts where the limit per xattr is 64k). This new "max_xattr" option can be specified with both -fsdev and -virtfs command line options, with the "local" and the "synth" fs drivers. The previous limit of 1024 is preserved as the default value. Link: https://lore.kernel.org/qemu-devel/b7631ac0d8dde0629bc7c4f2c4185d9f57b962b4.1781361555.git.qemu_oss@crudebyte.com Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>

Christian Schoenebeck committed Jun 13, 2026 at 16:55 UTC e6116a81f04c48af9530d984d16ef4ed4346e865
7 files changed +43 -4
fsdev/file-op-9p.h
+2
@@ -101,6 +101,8 @@ typedef struct FsDriverEntry {
101 FsThrottle fst;
102 mode_t fmode;
103 mode_t dmode;
104 + /* temporary storage for parse_opts only */
105 + uint32_t max_xattr;
106 } FsDriverEntry;
107
108 struct FsContext {
fsdev/qemu-fsdev-opts.c
+6
@@ -46,6 +46,9 @@ static QemuOptsList qemu_fsdev_opts = {
46 }, {
47 .name = "dmode",
48 .type = QEMU_OPT_NUMBER,
49 + }, {
50 + .name = "max_xattr",
51 + .type = QEMU_OPT_NUMBER,
52 },
53
54 THROTTLE_OPTS,
@@ -92,6 +95,9 @@ static QemuOptsList qemu_virtfs_opts = {
95 }, {
96 .name = "dmode",
97 .type = QEMU_OPT_NUMBER,
98 + }, {
99 + .name = "max_xattr",
100 + .type = QEMU_OPT_NUMBER,
101 },
102
103 { /*End of list */ }
fsdev/qemu-fsdev.c
+1 -1
@@ -45,7 +45,7 @@ typedef struct FsDriverListEntry {
45 static QTAILQ_HEAD(, FsDriverListEntry) fsdriver_entries =
46 QTAILQ_HEAD_INITIALIZER(fsdriver_entries);
47
48 -#define COMMON_FS_DRIVER_OPTIONS "id", "fsdriver", "readonly"
48 +#define COMMON_FS_DRIVER_OPTIONS "id", "fsdriver", "readonly", "max_xattr"
49
50 static FsDriverTable FsDrivers[] = {
51 {
hw/9pfs/9p-local.c
+9
@@ -1527,6 +1527,15 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp)
1527 const char *path = qemu_opt_get(opts, "path");
1528 const char *multidevs = qemu_opt_get(opts, "multidevs");
1529
1530 + uint64_t val = qemu_opt_get_number(opts, "max_xattr",
1531 + V9FS_MAX_XATTR_DEFAULT);
1532 + if (val > UINT32_MAX) {
1533 + error_setg(errp, "max_xattr value '%s' too large",
1534 + qemu_opt_get(opts, "max_xattr"));
1535 + return -1;
1536 + }
1537 + fse->max_xattr = val;
1538 +
1539 if (!sec_model) {
1540 error_setg(errp, "security_model property not set");
1541 error_append_security_model_hint(errp);
hw/9pfs/9p-synth.c
+17
@@ -25,6 +25,8 @@
25 #include "qemu/rcu_queue.h"
26 #include "qemu/cutils.h"
27 #include "system/qtest.h"
28 +#include "qapi/error.h"
29 +#include "qemu/option.h"
30
31 /* Root node for synth file system */
32 static V9fsSynthNode synth_root = {
@@ -629,12 +631,27 @@ static int synth_init(FsContext *ctx, Error **errp)
631 return 0;
632 }
633
634 +static int synth_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp)
635 +{
636 + uint64_t val = qemu_opt_get_number(opts, "max_xattr",
637 + V9FS_MAX_XATTR_DEFAULT);
638 + if (val > UINT32_MAX) {
639 + error_setg(errp, "max_xattr value '%s' too large",
640 + qemu_opt_get(opts, "max_xattr"));
641 + return -1;
642 + }
643 + fse->max_xattr = val;
644 +
645 + return 0;
646 +}
647 +
648 static bool synth_has_valid_file_handle(int fid_type, V9fsFidOpenState *fs)
649 {
650 return false;
651 }
652
653 FileOperations synth_ops = {
654 + .parse_opts = synth_parse_opts,
655 .init = synth_init,
656 .lstat = synth_lstat,
657 .readlink = synth_readlink,
hw/9pfs/9p.c
+2 -2
@@ -4483,8 +4483,8 @@ int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
4483
4484 s->reclaiming = false;
4485
4486 - /* init xattr FID limit */
4487 - s->ctx.xattr_fid_limit = V9FS_MAX_XATTR_DEFAULT;
4486 + /* init xattr FID limit from fsdev config */
4487 + s->ctx.xattr_fid_limit = fse->max_xattr;
4488 s->ctx.xattr_fid_count = 0;
4489
4490 rc = 0;
system/vl.c
+6 -1
@@ -3260,7 +3260,7 @@ void qemu_init(int argc, char **argv)
3260 QemuOpts *fsdev;
3261 QemuOpts *device;
3262 const char *writeout, *sock_fd, *socket, *path, *security_model,
3263 - *multidevs;
3263 + *multidevs, *max_xattr_str;
3264
3265 olist = qemu_find_opts("virtfs");
3266 if (!olist) {
@@ -3324,6 +3324,11 @@ void qemu_init(int argc, char **argv)
3324 if (multidevs) {
3325 qemu_opt_set(fsdev, "multidevs", multidevs, &error_abort);
3326 }
3327 + max_xattr_str = qemu_opt_get(opts, "max_xattr");
3328 + if (max_xattr_str) {
3329 + qemu_opt_set(fsdev, "max_xattr", max_xattr_str,
3330 + &error_abort);
3331 + }
3332 device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
3333 &error_abort);
3334 qemu_opt_set(device, "driver", "virtio-9p-pci", &error_abort);