qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qemu-fsdev.c (4873B)


      1 /*
      2  * 9p
      3  *
      4  * Copyright IBM, Corp. 2010
      5  *
      6  * Authors:
      7  *  Gautham R Shenoy <ego@in.ibm.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2.  See
     10  * the COPYING file in the top-level directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "qapi/error.h"
     15 #include "qemu-fsdev.h"
     16 #include "qemu/queue.h"
     17 #include "qemu/config-file.h"
     18 #include "qemu/error-report.h"
     19 #include "qemu/option.h"
     20 
     21 /*
     22  * A table to store the various file systems and their callback operations.
     23  * -----------------
     24  * fstype | ops
     25  * -----------------
     26  *  local | local_ops
     27  *  .     |
     28  *  .     |
     29  *  .     |
     30  *  .     |
     31  * -----------------
     32  *  etc
     33  */
     34 typedef struct FsDriverTable {
     35     const char *name;
     36     FileOperations *ops;
     37     const char **opts;
     38 } FsDriverTable;
     39 
     40 typedef struct FsDriverListEntry {
     41     FsDriverEntry fse;
     42     QTAILQ_ENTRY(FsDriverListEntry) next;
     43 } FsDriverListEntry;
     44 
     45 static QTAILQ_HEAD(, FsDriverListEntry) fsdriver_entries =
     46     QTAILQ_HEAD_INITIALIZER(fsdriver_entries);
     47 
     48 #define COMMON_FS_DRIVER_OPTIONS "id", "fsdriver", "readonly"
     49 
     50 static FsDriverTable FsDrivers[] = {
     51     {
     52         .name = "local",
     53         .ops = &local_ops,
     54         .opts = (const char * []) {
     55             COMMON_FS_DRIVER_OPTIONS,
     56             "security_model",
     57             "path",
     58             "writeout",
     59             "fmode",
     60             "dmode",
     61             "multidevs",
     62             "throttling.bps-total",
     63             "throttling.bps-read",
     64             "throttling.bps-write",
     65             "throttling.iops-total",
     66             "throttling.iops-read",
     67             "throttling.iops-write",
     68             "throttling.bps-total-max",
     69             "throttling.bps-read-max",
     70             "throttling.bps-write-max",
     71             "throttling.iops-total-max",
     72             "throttling.iops-read-max",
     73             "throttling.iops-write-max",
     74             "throttling.bps-total-max-length",
     75             "throttling.bps-read-max-length",
     76             "throttling.bps-write-max-length",
     77             "throttling.iops-total-max-length",
     78             "throttling.iops-read-max-length",
     79             "throttling.iops-write-max-length",
     80             "throttling.iops-size",
     81             NULL
     82         },
     83     },
     84     {
     85         .name = "synth",
     86         .ops = &synth_ops,
     87         .opts = (const char * []) {
     88             COMMON_FS_DRIVER_OPTIONS,
     89             NULL
     90         },
     91     },
     92     {
     93         .name = "proxy",
     94         .ops = &proxy_ops,
     95         .opts = (const char * []) {
     96             COMMON_FS_DRIVER_OPTIONS,
     97             "socket",
     98             "sock_fd",
     99             "writeout",
    100             NULL
    101         },
    102     },
    103 };
    104 
    105 static int validate_opt(void *opaque, const char *name, const char *value,
    106                         Error **errp)
    107 {
    108     FsDriverTable *drv = opaque;
    109     const char **opt;
    110 
    111     for (opt = drv->opts; *opt; opt++) {
    112         if (!strcmp(*opt, name)) {
    113             return 0;
    114         }
    115     }
    116 
    117     error_setg(errp, "'%s' is invalid for fsdriver '%s'", name, drv->name);
    118     return -1;
    119 }
    120 
    121 int qemu_fsdev_add(QemuOpts *opts, Error **errp)
    122 {
    123     int i;
    124     struct FsDriverListEntry *fsle;
    125     const char *fsdev_id = qemu_opts_id(opts);
    126     const char *fsdriver = qemu_opt_get(opts, "fsdriver");
    127     const char *writeout = qemu_opt_get(opts, "writeout");
    128     bool ro = qemu_opt_get_bool(opts, "readonly", 0);
    129 
    130     if (!fsdev_id) {
    131         error_setg(errp, "fsdev: No id specified");
    132         return -1;
    133     }
    134 
    135     if (fsdriver) {
    136         for (i = 0; i < ARRAY_SIZE(FsDrivers); i++) {
    137             if (strcmp(FsDrivers[i].name, fsdriver) == 0) {
    138                 break;
    139             }
    140         }
    141 
    142         if (i == ARRAY_SIZE(FsDrivers)) {
    143             error_setg(errp, "fsdev: fsdriver %s not found", fsdriver);
    144             return -1;
    145         }
    146     } else {
    147         error_setg(errp, "fsdev: No fsdriver specified");
    148         return -1;
    149     }
    150 
    151     if (qemu_opt_foreach(opts, validate_opt, &FsDrivers[i], errp)) {
    152         return -1;
    153     }
    154 
    155     fsle = g_malloc0(sizeof(*fsle));
    156     fsle->fse.fsdev_id = g_strdup(fsdev_id);
    157     fsle->fse.ops = FsDrivers[i].ops;
    158     if (writeout) {
    159         if (!strcmp(writeout, "immediate")) {
    160             fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
    161         }
    162     }
    163     if (ro) {
    164         fsle->fse.export_flags |= V9FS_RDONLY;
    165     } else {
    166         fsle->fse.export_flags &= ~V9FS_RDONLY;
    167     }
    168 
    169     if (fsle->fse.ops->parse_opts) {
    170         if (fsle->fse.ops->parse_opts(opts, &fsle->fse, errp)) {
    171             g_free(fsle->fse.fsdev_id);
    172             g_free(fsle);
    173             return -1;
    174         }
    175     }
    176 
    177     QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
    178     return 0;
    179 }
    180 
    181 FsDriverEntry *get_fsdev_fsentry(char *id)
    182 {
    183     if (id) {
    184         struct FsDriverListEntry *fsle;
    185 
    186         QTAILQ_FOREACH(fsle, &fsdriver_entries, next) {
    187             if (strcmp(fsle->fse.fsdev_id, id) == 0) {
    188                 return &fsle->fse;
    189             }
    190         }
    191     }
    192     return NULL;
    193 }