mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Qdisk supports qcow and qcow2, extend it to also support qed disk format. Signed-off-by: Cédric Bosdonnat <cbosdonnat@suse.com> [ wei: regenerate libxlu_disk_l.{c,h} ] Acked-by: Wei Liu <wei.liu2@citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
279 lines
10 KiB
Plaintext
279 lines
10 KiB
Plaintext
/* -*- fundamental -*- */
|
|
/*
|
|
* libxlu_disk_l.l - parser for disk specification strings
|
|
*
|
|
* Copyright (C) 2011 Citrix Ltd.
|
|
* Author Ian Jackson <ian.jackson@eu.citrix.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*/
|
|
|
|
/*
|
|
* Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem,
|
|
* because the target string might in theory contain "," which is the
|
|
* delimiter we use for stripping off things on the RHS, and ":",
|
|
* which is the delimiter we use for stripping off things on the LHS.
|
|
*
|
|
* In this parser we do not support such target strings in the old
|
|
* syntax; if the target string has to contain "," or ":" the new
|
|
* syntax's "target=" should be used.
|
|
*/
|
|
|
|
%top{
|
|
#include "libxl_osdeps.h" /* must come before any other headers */
|
|
}
|
|
|
|
%{
|
|
#include "libxlu_disk_i.h"
|
|
|
|
#define YY_NO_INPUT
|
|
|
|
/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes
|
|
* it to fail to declare these functions, which it defines. So declare
|
|
* them ourselves. Hopefully we won't have to simultaneously support
|
|
* a flex version which declares these differently somehow. */
|
|
int xlu__disk_yyget_column(yyscan_t yyscanner);
|
|
void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner);
|
|
|
|
|
|
/*----- useful macros and functions used in actions -----
|
|
* we use macros in the actual rules to keep the actions short
|
|
* and particularly to avoid repeating boilerplate values such as
|
|
* DPC->disk, yytext, etc. */
|
|
|
|
/* Sets an enum, checking it hasn't already been set to a different value */
|
|
#define DSET(dpc,member,enumname,str,valname) do{ \
|
|
if (dpc->disk->member != LIBXL_DISK_##enumname##_UNKNOWN && \
|
|
dpc->disk->member != LIBXL_DISK_##enumname##_##valname) { \
|
|
xlu__disk_err(dpc, str, TOSTRING(member) " respecified"); \
|
|
} else { \
|
|
dpc->disk->member = LIBXL_DISK_##enumname##_##valname; \
|
|
} \
|
|
}while(0)
|
|
|
|
/* For actions whose patterns contain '=', finds the start of the value */
|
|
#define FROMEQUALS (strchr(yytext,'=')+1)
|
|
|
|
/* Chops the delimiter off, modifying yytext and yyleng. */
|
|
#define STRIP(delim) do{ \
|
|
if (yyleng>0 && yytext[yyleng-1]==(delim)) \
|
|
yytext[--yyleng] = 0; \
|
|
}while(0)
|
|
|
|
/* Sets a string value, checking it hasn't been set already. */
|
|
#define SAVESTRING(what,loc,val) do{ \
|
|
savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \
|
|
}while(0)
|
|
static void savestring(DiskParseContext *dpc, const char *what_respecified,
|
|
char **update, const char *value) {
|
|
if (*update) {
|
|
if (**update) { xlu__disk_err(dpc,value,what_respecified); return; }
|
|
free(*update); /* do not complain about overwriting empty strings */
|
|
}
|
|
*update = strdup(value);
|
|
}
|
|
|
|
#define DPC dpc /* our convention in lexer helper functions */
|
|
|
|
/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */
|
|
static void setaccess(DiskParseContext *dpc, const char *str) {
|
|
if (!strcmp(str, "r") || !strcmp(str, "ro")) {
|
|
dpc->disk->readwrite = 0;
|
|
} else if (!strcmp(str, "rw") || !strcmp(str, "w") || !strcmp(str,"")) {
|
|
dpc->disk->readwrite = 1;
|
|
} else {
|
|
xlu__disk_err(dpc,str,"unknown value for access");
|
|
}
|
|
}
|
|
|
|
/* Sets ->format from the string. IDL should provide something for this. */
|
|
static void setformat(DiskParseContext *dpc, const char *str) {
|
|
if (!strcmp(str,"")) DSET(dpc,format,FORMAT,str,RAW);
|
|
else if (!strcmp(str,"raw")) DSET(dpc,format,FORMAT,str,RAW);
|
|
else if (!strcmp(str,"qcow")) DSET(dpc,format,FORMAT,str,QCOW);
|
|
else if (!strcmp(str,"qcow2")) DSET(dpc,format,FORMAT,str,QCOW2);
|
|
else if (!strcmp(str,"vhd")) DSET(dpc,format,FORMAT,str,VHD);
|
|
else if (!strcmp(str,"empty")) DSET(dpc,format,FORMAT,str,EMPTY);
|
|
else if (!strcmp(str,"qed")) DSET(dpc,format,FORMAT,str,QED);
|
|
else xlu__disk_err(dpc,str,"unknown value for format");
|
|
}
|
|
|
|
/* Sets ->backend from the string. IDL should provide something for this. */
|
|
static void setbackendtype(DiskParseContext *dpc, const char *str) {
|
|
if ( !strcmp(str,"phy")) DSET(dpc,backend,BACKEND,str,PHY);
|
|
else if (!strcmp(str,"tap")) DSET(dpc,backend,BACKEND,str,TAP);
|
|
else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
|
|
else xlu__disk_err(dpc,str,"unknown value for backendtype");
|
|
}
|
|
|
|
/* Sets ->colo-port from the string. COLO need this. */
|
|
static void setcoloport(DiskParseContext *dpc, const char *str) {
|
|
int port = atoi(str);
|
|
if (port) {
|
|
dpc->disk->colo_port = port;
|
|
} else {
|
|
xlu__disk_err(dpc,str,"unknown value for colo_port");
|
|
}
|
|
}
|
|
|
|
#define DEPRECATE(usewhatinstead) /* not currently reported */
|
|
|
|
/* Handles a vdev positional parameter which includes a devtype. */
|
|
static int vdev_and_devtype(DiskParseContext *dpc, char *str) {
|
|
/* returns 1 if it was <vdev>:<devtype>, 0 (doing nothing) otherwise */
|
|
char *colon = strrchr(str, ':');
|
|
if (!colon)
|
|
return 0;
|
|
|
|
DEPRECATE("use `devtype=...'");
|
|
*colon++ = 0;
|
|
SAVESTRING("vdev", vdev, str);
|
|
|
|
if (!strcmp(colon,"cdrom")) {
|
|
DPC->disk->is_cdrom = 1;
|
|
} else if (!strcmp(colon,"disk")) {
|
|
DPC->disk->is_cdrom = 0;
|
|
} else {
|
|
xlu__disk_err(DPC,colon,"unknown deprecated type");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#undef DPC /* needs to be defined differently the actual lexer */
|
|
#define DPC ((DiskParseContext*)yyextra)
|
|
|
|
%}
|
|
|
|
%option warn
|
|
%option nodefault
|
|
%option batch
|
|
%option 8bit
|
|
%option noyywrap
|
|
%option reentrant
|
|
%option prefix="xlu__disk_yy"
|
|
%option nounput
|
|
|
|
%x LEXERR
|
|
|
|
%%
|
|
|
|
/*----- the scanner rules which do the parsing -----*/
|
|
|
|
[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ }
|
|
|
|
/* ordinary parameters setting enums or strings */
|
|
|
|
format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); }
|
|
|
|
cdrom,? { DPC->disk->is_cdrom = 1; }
|
|
devtype=cdrom,? { DPC->disk->is_cdrom = 1; }
|
|
devtype=disk,? { DPC->disk->is_cdrom = 0; }
|
|
devtype=[^,]*,? { xlu__disk_err(DPC,yytext,"unknown value for type"); }
|
|
|
|
access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); }
|
|
backend=[^,]*,? { STRIP(','); SAVESTRING("backend", backend_domname, FROMEQUALS); }
|
|
backendtype=[^,]*,? { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
|
|
|
|
vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
|
|
script=[^,]*,? { STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
|
|
direct-io-safe,? { DPC->disk->direct_io_safe = 1; }
|
|
discard,? { libxl_defbool_set(&DPC->disk->discard_enable, true); }
|
|
no-discard,? { libxl_defbool_set(&DPC->disk->discard_enable, false); }
|
|
/* Note that the COLO configuration settings should be considered unstable.
|
|
* They may change incompatibly in future versions of Xen. */
|
|
colo,? { libxl_defbool_set(&DPC->disk->colo_enable, true); }
|
|
no-colo,? { libxl_defbool_set(&DPC->disk->colo_enable, false); }
|
|
colo-host=[^,]*,? { STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
|
|
colo-port=[^,]*,? { STRIP(','); setcoloport(DPC, FROMEQUALS); }
|
|
colo-export=[^,]*,? { STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
|
|
active-disk=[^,]*,? { STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
|
|
hidden-disk=[^,]*,? { STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
|
|
|
|
/* the target magic parameter, eats the rest of the string */
|
|
|
|
target=.* { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
|
|
|
|
/* unknown parameters */
|
|
|
|
[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC,yytext,"unknown parameter"); }
|
|
|
|
/* deprecated prefixes */
|
|
|
|
/* the "/.*" in these patterns ensures that they count as if they
|
|
* matched the whole string, so these patterns take precedence */
|
|
|
|
(raw|qcow2?|vhd):/.* {
|
|
STRIP(':');
|
|
DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
|
|
setformat(DPC, yytext);
|
|
}
|
|
|
|
(iscsi|e?nbd|drbd):/.* {
|
|
char *newscript;
|
|
STRIP(':');
|
|
DPC->had_depr_prefix=1; DEPRECATE("use `script=...'");
|
|
if (asprintf(&newscript, "block-%s", yytext) < 0) {
|
|
xlu__disk_err(DPC,yytext,"unable to format script");
|
|
return 0;
|
|
}
|
|
savestring(DPC, "script respecified",
|
|
&DPC->disk->script, newscript);
|
|
free(newscript);
|
|
}
|
|
|
|
tapdisk:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
tap2?:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
aio:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
ioemu:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
file:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
phy:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); }
|
|
|
|
[a-z][a-z0-9]*:/([^a-z0-9].*)? {
|
|
xlu__disk_err(DPC,yytext,"unknown deprecated disk prefix");
|
|
return 0;
|
|
}
|
|
|
|
/* positional parameters */
|
|
|
|
[^=,]*,|[^=,]+,? {
|
|
STRIP(',');
|
|
|
|
if (DPC->err) {
|
|
/* previous errors may just lead to subsequent ones */
|
|
} else if (!DPC->disk->pdev_path) {
|
|
SAVESTRING("target", pdev_path, yytext);
|
|
} else if (!DPC->had_depr_prefix &&
|
|
DPC->disk->format == LIBXL_DISK_FORMAT_UNKNOWN) {
|
|
if (!*DPC->disk->pdev_path && vdev_and_devtype(DPC,yytext)) {
|
|
DPC->disk->format = LIBXL_DISK_FORMAT_EMPTY;
|
|
} else {
|
|
setformat(DPC,yytext);
|
|
}
|
|
} else if (!DPC->disk->vdev) {
|
|
if (!vdev_and_devtype(DPC,yytext))
|
|
SAVESTRING("vdev", vdev, yytext);
|
|
} else if (!DPC->access_set) {
|
|
DPC->access_set = 1;
|
|
setaccess(DPC,yytext);
|
|
} else {
|
|
xlu__disk_err(DPC,yytext,"too many positional parameters");
|
|
return 0; /* don't print any more errors */
|
|
}
|
|
}
|
|
|
|
. {
|
|
BEGIN(LEXERR);
|
|
yymore();
|
|
}
|
|
<LEXERR>.* {
|
|
xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
|
|
}
|