Files
xen/tools/libxl/libxlu_disk_l.l
T
Cédric Bosdonnat 1035fe9b16 libxl: QED disks support
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>
2016-12-13 20:25:25 +00:00

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;
}