mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
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>
183 lines
4.5 KiB
C
183 lines
4.5 KiB
C
/*
|
|
* 9p
|
|
*
|
|
* Copyright IBM, Corp. 2010
|
|
*
|
|
* Authors:
|
|
* Gautham R Shenoy <ego@in.ibm.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
* the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu-fsdev.h"
|
|
#include "qemu/queue.h"
|
|
#include "qemu/config-file.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/option.h"
|
|
|
|
/*
|
|
* A table to store the various file systems and their callback operations.
|
|
* -----------------
|
|
* fstype | ops
|
|
* -----------------
|
|
* local | local_ops
|
|
* . |
|
|
* . |
|
|
* . |
|
|
* . |
|
|
* -----------------
|
|
* etc
|
|
*/
|
|
typedef struct FsDriverTable {
|
|
const char *name;
|
|
FileOperations *ops;
|
|
const char **opts;
|
|
} FsDriverTable;
|
|
|
|
typedef struct FsDriverListEntry {
|
|
FsDriverEntry fse;
|
|
QTAILQ_ENTRY(FsDriverListEntry) next;
|
|
} FsDriverListEntry;
|
|
|
|
static QTAILQ_HEAD(, FsDriverListEntry) fsdriver_entries =
|
|
QTAILQ_HEAD_INITIALIZER(fsdriver_entries);
|
|
|
|
#define COMMON_FS_DRIVER_OPTIONS "id", "fsdriver", "readonly", "max_xattr"
|
|
|
|
static FsDriverTable FsDrivers[] = {
|
|
{
|
|
.name = "local",
|
|
.ops = &local_ops,
|
|
.opts = (const char * []) {
|
|
COMMON_FS_DRIVER_OPTIONS,
|
|
"security_model",
|
|
"path",
|
|
"writeout",
|
|
"fmode",
|
|
"dmode",
|
|
"multidevs",
|
|
"throttling.bps-total",
|
|
"throttling.bps-read",
|
|
"throttling.bps-write",
|
|
"throttling.iops-total",
|
|
"throttling.iops-read",
|
|
"throttling.iops-write",
|
|
"throttling.bps-total-max",
|
|
"throttling.bps-read-max",
|
|
"throttling.bps-write-max",
|
|
"throttling.iops-total-max",
|
|
"throttling.iops-read-max",
|
|
"throttling.iops-write-max",
|
|
"throttling.bps-total-max-length",
|
|
"throttling.bps-read-max-length",
|
|
"throttling.bps-write-max-length",
|
|
"throttling.iops-total-max-length",
|
|
"throttling.iops-read-max-length",
|
|
"throttling.iops-write-max-length",
|
|
"throttling.iops-size",
|
|
NULL
|
|
},
|
|
},
|
|
{
|
|
.name = "synth",
|
|
.ops = &synth_ops,
|
|
.opts = (const char * []) {
|
|
COMMON_FS_DRIVER_OPTIONS,
|
|
NULL
|
|
},
|
|
},
|
|
};
|
|
|
|
static int validate_opt(void *opaque, const char *name, const char *value,
|
|
Error **errp)
|
|
{
|
|
FsDriverTable *drv = opaque;
|
|
const char **opt;
|
|
|
|
for (opt = drv->opts; *opt; opt++) {
|
|
if (!strcmp(*opt, name)) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
error_setg(errp, "'%s' is invalid for fsdriver '%s'", name, drv->name);
|
|
return -1;
|
|
}
|
|
|
|
int qemu_fsdev_add(QemuOpts *opts, Error **errp)
|
|
{
|
|
int i;
|
|
struct FsDriverListEntry *fsle;
|
|
const char *fsdev_id = qemu_opts_id(opts);
|
|
const char *fsdriver = qemu_opt_get(opts, "fsdriver");
|
|
const char *writeout = qemu_opt_get(opts, "writeout");
|
|
bool ro = qemu_opt_get_bool(opts, "readonly", 0);
|
|
|
|
if (!fsdev_id) {
|
|
error_setg(errp, "fsdev: No id specified");
|
|
return -1;
|
|
}
|
|
|
|
if (fsdriver) {
|
|
for (i = 0; i < ARRAY_SIZE(FsDrivers); i++) {
|
|
if (strcmp(FsDrivers[i].name, fsdriver) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == ARRAY_SIZE(FsDrivers)) {
|
|
error_setg(errp, "fsdev: fsdriver %s not found", fsdriver);
|
|
return -1;
|
|
}
|
|
} else {
|
|
error_setg(errp, "fsdev: No fsdriver specified");
|
|
return -1;
|
|
}
|
|
|
|
if (qemu_opt_foreach(opts, validate_opt, &FsDrivers[i], errp)) {
|
|
return -1;
|
|
}
|
|
|
|
fsle = g_malloc0(sizeof(*fsle));
|
|
fsle->fse.fsdev_id = g_strdup(fsdev_id);
|
|
fsle->fse.ops = FsDrivers[i].ops;
|
|
if (writeout) {
|
|
if (!strcmp(writeout, "immediate")) {
|
|
fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
|
|
}
|
|
}
|
|
if (ro) {
|
|
fsle->fse.export_flags |= V9FS_RDONLY;
|
|
} else {
|
|
fsle->fse.export_flags &= ~V9FS_RDONLY;
|
|
}
|
|
|
|
if (fsle->fse.ops->parse_opts) {
|
|
if (fsle->fse.ops->parse_opts(opts, &fsle->fse, errp)) {
|
|
g_free(fsle->fse.fsdev_id);
|
|
g_free(fsle);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
|
|
return 0;
|
|
}
|
|
|
|
FsDriverEntry *get_fsdev_fsentry(char *id)
|
|
{
|
|
if (id) {
|
|
struct FsDriverListEntry *fsle;
|
|
|
|
QTAILQ_FOREACH(fsle, &fsdriver_entries, next) {
|
|
if (strcmp(fsle->fse.fsdev_id, id) == 0) {
|
|
return &fsle->fse;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|