Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
cfb192ad
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
cfb192ad
编写于
10月 22, 2007
作者:
D
Daniel Veillard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
* docs/format.html docs/libvir.html: documentation cleaups
from Jim Paris Daniel
上级
a87420ae
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
505 addition
and
376 deletion
+505
-376
ChangeLog
ChangeLog
+5
-0
docs/format.html
docs/format.html
+4
-8
docs/libvir.html
docs/libvir.html
+4
-8
src/xen_internal.c
src/xen_internal.c
+13
-10
src/xen_unified.c
src/xen_unified.c
+59
-0
src/xen_unified.h
src/xen_unified.h
+3
-0
src/xend_internal.c
src/xend_internal.c
+1
-347
src/xml.c
src/xml.c
+393
-0
src/xml.h
src/xml.h
+23
-3
未找到文件。
ChangeLog
浏览文件 @
cfb192ad
Mon Oct 22 22:27:40 CEST 2007 Daniel Veillard <veillard@redhat.com>
* docs/format.html docs/libvir.html: documentation cleaups
from Jim Paris
Mon Oct 22 15:05:30 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/xend_internal.c: update to cpuset parsing code for NUMA
...
...
docs/format.html
浏览文件 @
cfb192ad
...
...
@@ -230,7 +230,7 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
<pre>
<
interface type='user'/
>
</pre>
<pre>
<
interface type='user'
>
<
mac address="11:22:33:44:55:66
:
/
>
<
mac address="11:22:33:44:55:66
"
/
>
<
/interface
>
</pre>
</li>
...
...
@@ -253,7 +253,7 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
<
interface type='network'
>
<
source network='default'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66
:
/
>
<
mac address="11:22:33:44:55:66
"
/
>
<
/interface
>
</pre>
</li>
...
...
@@ -273,12 +273,8 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
<
interface type='bridge'
>
<
source dev='br0'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66:/
>
<
/interface
>
<
interface type='bridge'
>
<
source dev='br0'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66:/
>
<
/interface
>
</pre>
<
mac address="11:22:33:44:55:66"/
>
<
/interface
>
</pre>
</li>
<li>
Generic connection to LAN
<p>
Provides a means for the administrator to execute an arbitrary script
...
...
docs/libvir.html
浏览文件 @
cfb192ad
...
...
@@ -964,7 +964,7 @@ support a variety of options:</p>
<pre>
<
interface type='user'/
>
</pre>
<pre>
<
interface type='user'
>
<
mac address="11:22:33:44:55:66
:
/
>
<
mac address="11:22:33:44:55:66
"
/
>
<
/interface
>
</pre>
</li>
...
...
@@ -987,7 +987,7 @@ support a variety of options:</p>
<
interface type='network'
>
<
source network='default'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66
:
/
>
<
mac address="11:22:33:44:55:66
"
/
>
<
/interface
>
</pre>
</li>
...
...
@@ -1007,12 +1007,8 @@ support a variety of options:</p>
<
interface type='bridge'
>
<
source dev='br0'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66:/
>
<
/interface
>
<
interface type='bridge'
>
<
source dev='br0'/
>
<
target dev='vnet7'/
>
<
mac address="11:22:33:44:55:66:/
>
<
/interface
>
</pre>
<
mac address="11:22:33:44:55:66"/
>
<
/interface
>
</pre>
</li>
<li>
Generic connection to LAN
<p>
Provides a means for the administrator to execute an arbitrary script
...
...
src/xen_internal.c
浏览文件 @
cfb192ad
...
...
@@ -3035,24 +3035,27 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
xen_op_v2_sys
op_sys
;
int
i
,
j
,
ret
;
xenUnifiedPrivatePtr
priv
;
static
int
nbNodeCells
=
-
1
;
virNodeInfo
nodeInfo
;
int
nbNodeCells
;
if
(
conn
==
NULL
)
{
virXenErrorFunc
(
VIR_ERR_INVALID_ARG
,
__FUNCTION__
,
"invalid argument"
,
0
);
return
-
1
;
}
if
(
nbNodeCells
==
-
1
)
{
if
(
xenDaemonNodeGetInfo
(
conn
,
&
nodeInfo
))
{
virXenErrorFunc
(
VIR_ERR_XEN_CALL
,
__FUNCTION__
,
"cannot determine actual number of cells"
,
0
);
return
-
1
;
}
nbNodeCells
=
nodeInfo
.
nodes
;
nbNodeCells
=
xenNbCells
(
conn
);
if
(
nbNodeCells
<
0
)
{
virXenErrorFunc
(
VIR_ERR_XEN_CALL
,
__FUNCTION__
,
"cannot determine actual number of cells"
,
0
);
return
(
-
1
);
}
if
((
conn
==
NULL
)
||
(
maxCells
<
1
)
||
(
startCell
>=
nbNodeCells
))
{
if
((
maxCells
<
1
)
||
(
startCell
>=
nbNodeCells
))
{
virXenErrorFunc
(
VIR_ERR_INVALID_ARG
,
__FUNCTION__
,
"invalid argument"
,
0
);
return
-
1
;
}
/*
* Support only sys_interface_version >=4
*/
...
...
src/xen_unified.c
浏览文件 @
cfb192ad
...
...
@@ -37,6 +37,9 @@
#include "xs_internal.h"
#include "xm_internal.h"
static
int
xenUnifiedNodeGetInfo
(
virConnectPtr
conn
,
virNodeInfoPtr
info
);
/* The five Xen drivers below us. */
static
struct
xenUnifiedDriver
*
drivers
[
XEN_UNIFIED_NR_DRIVERS
]
=
{
[
XEN_UNIFIED_HYPERVISOR_OFFSET
]
=
&
xenHypervisorDriver
,
...
...
@@ -64,6 +67,62 @@ xenUnifiedError (virConnectPtr conn, virErrorNumber error, const char *info)
errmsg
,
info
,
NULL
,
0
,
0
,
errmsg
,
info
);
}
/*
* Helper functions currently used in the NUMA code
* Those variables should not be accessed directly but through helper
* functions xenNbCells() and xenNbCpu() available to all Xen backends
*/
static
int
nbNodeCells
=
-
1
;
static
int
nbNodeCpus
=
-
1
;
/**
* xenNumaInit:
* @conn: pointer to the hypervisor connection
*
* Initializer for previous variables. We currently assume that
* the number of physical CPU and the numebr of NUMA cell is fixed
* until reboot which might be false in future Xen implementations.
*/
static
void
xenNumaInit
(
virConnectPtr
conn
)
{
virNodeInfo
nodeInfo
;
int
ret
;
ret
=
xenUnifiedNodeGetInfo
(
conn
,
&
nodeInfo
);
if
(
ret
<
0
)
return
;
nbNodeCells
=
nodeInfo
.
nodes
;
nbNodeCpus
=
nodeInfo
.
cpus
;
}
/**
* xenNbCells:
* @conn: pointer to the hypervisor connection
*
* Number of NUMa cells present in the actual Node
*
* Returns the number of NUMA cells available on that Node
*/
int
xenNbCells
(
virConnectPtr
conn
)
{
if
(
nbNodeCells
<
0
)
xenNumaInit
(
conn
);
return
(
nbNodeCells
);
}
/**
* xenNbCpus:
* @conn: pointer to the hypervisor connection
*
* Number of NUMa cells present in the actual Node
*
* Returns the number of NUMA cells available on that Node
*/
int
xenNbCpus
(
virConnectPtr
conn
)
{
if
(
nbNodeCpus
<
0
)
xenNumaInit
(
conn
);
return
(
nbNodeCpus
);
}
/*----- Dispatch functions. -----*/
/* These dispatch functions follow the model used historically
...
...
src/xen_unified.h
浏览文件 @
cfb192ad
...
...
@@ -116,6 +116,9 @@ struct _xenUnifiedPrivate {
typedef
struct
_xenUnifiedPrivate
*
xenUnifiedPrivatePtr
;
int
xenNbCells
(
virConnectPtr
conn
);
int
xenNbCpus
(
virConnectPtr
conn
);
#ifdef __cplusplus
}
#endif
...
...
src/xend_internal.c
浏览文件 @
cfb192ad
...
...
@@ -1895,352 +1895,6 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
return
(
0
);
}
/**
* skipSpaces:
* @str: pointer to the char pointer used
*
* Skip potential blanks, this includes space tabs, line feed,
* carriage returns and also '\\' which can be erronously emitted
* by xend
*/
static
void
skipSpaces
(
const
char
**
str
)
{
const
char
*
cur
=
*
str
;
while
((
*
cur
==
' '
)
||
(
*
cur
==
'\t'
)
||
(
*
cur
==
'\n'
)
||
(
*
cur
==
'\r'
)
||
(
*
cur
==
'\\'
))
cur
++
;
*
str
=
cur
;
}
/**
* parseNumber:
* @str: pointer to the char pointer used
*
* Parse a number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static
int
parseNumber
(
const
char
**
str
)
{
int
ret
=
0
;
const
char
*
cur
=
*
str
;
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
return
(
-
1
);
while
((
*
cur
>=
'0'
)
&&
(
*
cur
<=
'9'
))
{
ret
=
ret
*
10
+
(
*
cur
-
'0'
);
cur
++
;
}
*
str
=
cur
;
return
(
ret
);
}
/**
* parseCpuNumber:
* @str: pointer to the char pointer used
* @maxcpu: maximum CPU number allowed
*
* Parse a CPU number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static
int
parseCpuNumber
(
const
char
**
str
,
int
maxcpu
)
{
int
ret
=
0
;
const
char
*
cur
=
*
str
;
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
return
(
-
1
);
while
((
*
cur
>=
'0'
)
&&
(
*
cur
<=
'9'
))
{
ret
=
ret
*
10
+
(
*
cur
-
'0'
);
if
(
ret
>
maxcpu
)
return
(
-
1
);
cur
++
;
}
*
str
=
cur
;
return
(
ret
);
}
#if 0 /* Not used yet */
/**
* saveCpuSet:
* @conn: connection
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Serialize the cpuset to a string
*
* Returns the new string NULL in case of error. The string need to be
* freed by the caller.
*/
static char *
saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
{
virBufferPtr buf;
char *ret;
int start, cur;
int first = 1;
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(NULL);
buf = virBufferNew(1000);
if (buf == NULL) {
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
return(NULL);
}
cur = 0;
start = -1;
while (cur < maxcpu) {
if (cpuset[cur]) {
if (start == -1)
start = cur;
} else if (start != -1) {
if (!first)
virBufferAdd(buf, ",", -1);
else
first = 0;
if (cur == start + 1)
virBufferVSprintf(buf, "%d", start);
else if (cur == start + 2)
virBufferVSprintf(buf, "%d,%d", start, cur - 1);
else
virBufferVSprintf(buf, "%d-%d", start, cur - 1);
start = -1;
}
cur++;
}
if (start != -1) {
if (!first)
virBufferAdd(buf, ",", -1);
if (maxcpu == start + 1)
virBufferVSprintf(buf, "%d", start);
else if (maxcpu == start + 2)
virBufferVSprintf(buf, "%d,%d", start, maxcpu - 1);
else
virBufferVSprintf(buf, "%d-%d", start, maxcpu - 1);
}
ret = virBufferContentAndFree(buf);
return(ret);
}
#endif
/**
* parseCpuSet:
* @str: pointer to a CPU set string pointer
* @sep: potential character used to mark the end of string if not 0
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
* to 1, and 0 otherwise. The syntax allows coma separated entries each
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
*
* Returns the number of CPU found in that set, or -1 in case of error.
* @cpuset is modified accordingly to the value parsed.
* @str is updated to the end of the part parsed
*/
static
int
parseCpuSet
(
virConnectPtr
conn
,
const
char
**
str
,
char
sep
,
char
*
cpuset
,
int
maxcpu
)
{
const
char
*
cur
;
int
ret
=
0
;
int
i
,
start
,
last
;
int
neg
=
0
;
if
((
str
==
NULL
)
||
(
cpuset
==
NULL
)
||
(
maxcpu
<=
0
)
||
(
maxcpu
>
100000
))
return
(
-
1
);
cur
=
*
str
;
skipSpaces
(
&
cur
);
if
(
*
cur
==
0
)
goto
parse_error
;
/* initialize cpumap to all 0s */
for
(
i
=
0
;
i
<
maxcpu
;
i
++
)
cpuset
[
i
]
=
0
;
ret
=
0
;
while
((
*
cur
!=
0
)
&&
(
*
cur
!=
sep
))
{
/*
* 3 constructs are allowed:
* - N : a single CPU number
* - N-M : a range of CPU numbers with N < M
* - ^N : remove a single CPU number from the current set
*/
if
(
*
cur
==
'^'
)
{
cur
++
;
neg
=
1
;
}
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
goto
parse_error
;
start
=
parseCpuNumber
(
&
cur
,
maxcpu
);
if
(
start
<
0
)
goto
parse_error
;
skipSpaces
(
&
cur
);
if
((
*
cur
==
','
)
||
(
*
cur
==
0
)
||
(
*
cur
==
sep
))
{
if
(
neg
)
{
if
(
cpuset
[
start
]
==
1
)
{
cpuset
[
start
]
=
0
;
ret
--
;
}
}
else
{
if
(
cpuset
[
start
]
==
0
)
{
cpuset
[
start
]
=
1
;
ret
++
;
}
}
}
else
if
(
*
cur
==
'-'
)
{
if
(
neg
)
goto
parse_error
;
cur
++
;
skipSpaces
(
&
cur
);
last
=
parseCpuNumber
(
&
cur
,
maxcpu
);
if
(
last
<
start
)
goto
parse_error
;
for
(
i
=
start
;
i
<=
last
;
i
++
)
{
if
(
cpuset
[
i
]
==
0
)
{
cpuset
[
i
]
=
1
;
ret
++
;
}
}
skipSpaces
(
&
cur
);
}
if
(
*
cur
==
','
)
{
cur
++
;
skipSpaces
(
&
cur
);
neg
=
0
;
}
else
if
((
*
cur
==
0
)
||
(
*
cur
==
sep
))
{
break
;
}
else
goto
parse_error
;
}
*
str
=
cur
;
return
(
ret
);
parse_error:
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
_
(
"topology cpuset syntax error"
));
return
(
-
1
);
}
/**
* parseXenCpuTopology:
* @xml: XML output buffer
* @str: the topology string
* @maxcpu: number of elements available in @cpuset
*
* Parse a Xend CPU topology string and build the associated XML
* format.
*
* Returns 0 in case of success, -1 in case of error
*/
static
int
parseTopology
(
virConnectPtr
conn
,
virBufferPtr
xml
,
const
char
*
str
,
int
maxcpu
)
{
const
char
*
cur
;
char
*
cpuset
=
NULL
;
int
cell
,
cpu
,
nb_cpus
;
int
ret
;
if
((
str
==
NULL
)
||
(
xml
==
NULL
)
||
(
maxcpu
<=
0
)
||
(
maxcpu
>
100000
))
return
(
-
1
);
cpuset
=
malloc
(
maxcpu
*
sizeof
(
char
));
if
(
cpuset
==
NULL
)
goto
memory_error
;
cur
=
str
;
while
(
*
cur
!=
0
)
{
/*
* Find the next NUMA cell described in the xend output
*/
cur
=
strstr
(
cur
,
"node"
);
if
(
cur
==
NULL
)
break
;
cur
+=
4
;
cell
=
parseNumber
(
&
cur
);
if
(
cell
<
0
)
goto
parse_error
;
skipSpaces
(
&
cur
);
if
(
*
cur
!=
':'
)
goto
parse_error
;
cur
++
;
skipSpaces
(
&
cur
);
if
(
!
strncmp
(
cur
,
"no cpus"
,
7
))
{
nb_cpus
=
0
;
for
(
cpu
=
0
;
cpu
<
maxcpu
;
cpu
++
)
cpuset
[
cpu
]
=
0
;
}
else
{
nb_cpus
=
parseCpuSet
(
conn
,
&
cur
,
'n'
,
cpuset
,
maxcpu
);
if
(
nb_cpus
<
0
)
goto
error
;
}
/*
* add xml for all cpus associated with that cell
*/
ret
=
virBufferVSprintf
(
xml
,
"\
<cell id='%d'>
\n
\
<cpus num='%d'>
\n
"
,
cell
,
nb_cpus
);
#ifdef STANDALONE
{
char
*
dump
;
dump
=
saveCpuSet
(
conn
,
cpuset
,
maxcpu
);
if
(
dump
!=
NULL
)
{
virBufferVSprintf
(
xml
,
" <dump>%s</dump>
\n
"
,
dump
);
free
(
dump
);
}
else
{
virBufferVSprintf
(
xml
,
" <error>%s</error>
\n
"
,
"Failed to dump CPU set"
);
}
}
#endif
if
(
ret
<
0
)
goto
memory_error
;
for
(
cpu
=
0
;
cpu
<
maxcpu
;
cpu
++
)
{
if
(
cpuset
[
cpu
]
==
1
)
{
ret
=
virBufferVSprintf
(
xml
,
"\
<cpu id='%d'/>
\n
"
,
cpu
);
if
(
ret
<
0
)
goto
memory_error
;
}
}
ret
=
virBufferAdd
(
xml
,
"\
</cpus>
\n
\
</cell>
\n
"
,
-
1
);
if
(
ret
<
0
)
goto
memory_error
;
}
free
(
cpuset
);
return
(
0
);
parse_error:
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
_
(
"topology syntax error"
));
error:
if
(
cpuset
!=
NULL
)
free
(
cpuset
);
return
(
-
1
);
memory_error:
if
(
cpuset
!=
NULL
)
free
(
cpuset
);
virXendError
(
conn
,
VIR_ERR_NO_MEMORY
,
_
(
"allocate buffer"
));
return
(
-
1
);
}
/**
* sexpr_to_xend_topology_xml:
* @root: an S-Expression describing a node
...
...
@@ -2276,7 +1930,7 @@ sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr
numCells
);
if
(
r
<
0
)
goto
vir_buffer_failed
;
r
=
parse
Topology
(
conn
,
xml
,
nodeToCpu
,
numCpus
);
r
=
virParseXenCpu
Topology
(
conn
,
xml
,
nodeToCpu
,
numCpus
);
if
(
r
<
0
)
goto
error
;
r
=
virBufferAdd
(
xml
,
"\
...
...
src/xml.c
浏览文件 @
cfb192ad
...
...
@@ -24,6 +24,7 @@
#include "xml.h"
#include "buf.h"
#include "xs_internal.h"
/* for xenStoreDomainGetNetworkID */
#include "xen_unified.h"
#ifndef PROXY
/**
...
...
@@ -48,6 +49,362 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int valu
errmsg
,
info
,
NULL
,
value
,
0
,
errmsg
,
info
,
value
);
}
/************************************************************************
* *
* Parser and converter for the CPUset strings used in libvirt *
* *
************************************************************************/
/**
* skipSpaces:
* @str: pointer to the char pointer used
*
* Skip potential blanks, this includes space tabs, line feed,
* carriage returns and also '\\' which can be erronously emitted
* by xend
*/
static
void
skipSpaces
(
const
char
**
str
)
{
const
char
*
cur
=
*
str
;
while
((
*
cur
==
' '
)
||
(
*
cur
==
'\t'
)
||
(
*
cur
==
'\n'
)
||
(
*
cur
==
'\r'
)
||
(
*
cur
==
'\\'
))
cur
++
;
*
str
=
cur
;
}
/**
* parseNumber:
* @str: pointer to the char pointer used
*
* Parse a number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static
int
parseNumber
(
const
char
**
str
)
{
int
ret
=
0
;
const
char
*
cur
=
*
str
;
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
return
(
-
1
);
while
((
*
cur
>=
'0'
)
&&
(
*
cur
<=
'9'
))
{
ret
=
ret
*
10
+
(
*
cur
-
'0'
);
cur
++
;
}
*
str
=
cur
;
return
(
ret
);
}
/**
* parseCpuNumber:
* @str: pointer to the char pointer used
* @maxcpu: maximum CPU number allowed
*
* Parse a CPU number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static
int
parseCpuNumber
(
const
char
**
str
,
int
maxcpu
)
{
int
ret
=
0
;
const
char
*
cur
=
*
str
;
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
return
(
-
1
);
while
((
*
cur
>=
'0'
)
&&
(
*
cur
<=
'9'
))
{
ret
=
ret
*
10
+
(
*
cur
-
'0'
);
if
(
ret
>
maxcpu
)
return
(
-
1
);
cur
++
;
}
*
str
=
cur
;
return
(
ret
);
}
/**
* saveCpuSet:
* @conn: connection
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Serialize the cpuset to a string
*
* Returns the new string NULL in case of error. The string need to be
* freed by the caller.
*/
static
char
*
saveCpuSet
(
virConnectPtr
conn
,
char
*
cpuset
,
int
maxcpu
)
{
virBufferPtr
buf
;
char
*
ret
;
int
start
,
cur
;
int
first
=
1
;
if
((
cpuset
==
NULL
)
||
(
maxcpu
<=
0
)
||
(
maxcpu
>
100000
))
return
(
NULL
);
buf
=
virBufferNew
(
1000
);
if
(
buf
==
NULL
)
{
virXMLError
(
conn
,
VIR_ERR_NO_MEMORY
,
_
(
"allocate buffer"
),
1000
);
return
(
NULL
);
}
cur
=
0
;
start
=
-
1
;
while
(
cur
<
maxcpu
)
{
if
(
cpuset
[
cur
])
{
if
(
start
==
-
1
)
start
=
cur
;
}
else
if
(
start
!=
-
1
)
{
if
(
!
first
)
virBufferAdd
(
buf
,
","
,
-
1
);
else
first
=
0
;
if
(
cur
==
start
+
1
)
virBufferVSprintf
(
buf
,
"%d"
,
start
);
else
if
(
cur
==
start
+
2
)
virBufferVSprintf
(
buf
,
"%d,%d"
,
start
,
cur
-
1
);
else
virBufferVSprintf
(
buf
,
"%d-%d"
,
start
,
cur
-
1
);
start
=
-
1
;
}
cur
++
;
}
if
(
start
!=
-
1
)
{
if
(
!
first
)
virBufferAdd
(
buf
,
","
,
-
1
);
if
(
maxcpu
==
start
+
1
)
virBufferVSprintf
(
buf
,
"%d"
,
start
);
else
if
(
maxcpu
==
start
+
2
)
virBufferVSprintf
(
buf
,
"%d,%d"
,
start
,
maxcpu
-
1
);
else
virBufferVSprintf
(
buf
,
"%d-%d"
,
start
,
maxcpu
-
1
);
}
ret
=
virBufferContentAndFree
(
buf
);
return
(
ret
);
}
/**
* virParseCpuSet:
* @str: pointer to a CPU set string pointer
* @sep: potential character used to mark the end of string if not 0
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
* to 1, and 0 otherwise. The syntax allows coma separated entries each
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
*
* Returns the number of CPU found in that set, or -1 in case of error.
* @cpuset is modified accordingly to the value parsed.
* @str is updated to the end of the part parsed
*/
int
virParseCpuSet
(
virConnectPtr
conn
,
const
char
**
str
,
char
sep
,
char
*
cpuset
,
int
maxcpu
)
{
const
char
*
cur
;
int
ret
=
0
;
int
i
,
start
,
last
;
int
neg
=
0
;
if
((
str
==
NULL
)
||
(
cpuset
==
NULL
)
||
(
maxcpu
<=
0
)
||
(
maxcpu
>
100000
))
return
(
-
1
);
cur
=
*
str
;
skipSpaces
(
&
cur
);
if
(
*
cur
==
0
)
goto
parse_error
;
/* initialize cpumap to all 0s */
for
(
i
=
0
;
i
<
maxcpu
;
i
++
)
cpuset
[
i
]
=
0
;
ret
=
0
;
while
((
*
cur
!=
0
)
&&
(
*
cur
!=
sep
))
{
/*
* 3 constructs are allowed:
* - N : a single CPU number
* - N-M : a range of CPU numbers with N < M
* - ^N : remove a single CPU number from the current set
*/
if
(
*
cur
==
'^'
)
{
cur
++
;
neg
=
1
;
}
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
goto
parse_error
;
start
=
parseCpuNumber
(
&
cur
,
maxcpu
);
if
(
start
<
0
)
goto
parse_error
;
skipSpaces
(
&
cur
);
if
((
*
cur
==
','
)
||
(
*
cur
==
0
)
||
(
*
cur
==
sep
))
{
if
(
neg
)
{
if
(
cpuset
[
start
]
==
1
)
{
cpuset
[
start
]
=
0
;
ret
--
;
}
}
else
{
if
(
cpuset
[
start
]
==
0
)
{
cpuset
[
start
]
=
1
;
ret
++
;
}
}
}
else
if
(
*
cur
==
'-'
)
{
if
(
neg
)
goto
parse_error
;
cur
++
;
skipSpaces
(
&
cur
);
last
=
parseCpuNumber
(
&
cur
,
maxcpu
);
if
(
last
<
start
)
goto
parse_error
;
for
(
i
=
start
;
i
<=
last
;
i
++
)
{
if
(
cpuset
[
i
]
==
0
)
{
cpuset
[
i
]
=
1
;
ret
++
;
}
}
skipSpaces
(
&
cur
);
}
if
(
*
cur
==
','
)
{
cur
++
;
skipSpaces
(
&
cur
);
neg
=
0
;
}
else
if
((
*
cur
==
0
)
||
(
*
cur
==
sep
))
{
break
;
}
else
goto
parse_error
;
}
*
str
=
cur
;
return
(
ret
);
parse_error:
virXMLError
(
conn
,
VIR_ERR_XEN_CALL
,
_
(
"topology cpuset syntax error"
),
0
);
return
(
-
1
);
}
/**
* virParseXenCpuTopology:
* @xml: XML output buffer
* @str: the topology string
* @maxcpu: number of elements available in @cpuset
*
* Parse a Xend CPU topology string and build the associated XML
* format.
*
* Returns 0 in case of success, -1 in case of error
*/
int
virParseXenCpuTopology
(
virConnectPtr
conn
,
virBufferPtr
xml
,
const
char
*
str
,
int
maxcpu
)
{
const
char
*
cur
;
char
*
cpuset
=
NULL
;
int
cell
,
cpu
,
nb_cpus
;
int
ret
;
if
((
str
==
NULL
)
||
(
xml
==
NULL
)
||
(
maxcpu
<=
0
)
||
(
maxcpu
>
100000
))
return
(
-
1
);
cpuset
=
malloc
(
maxcpu
*
sizeof
(
char
));
if
(
cpuset
==
NULL
)
goto
memory_error
;
cur
=
str
;
while
(
*
cur
!=
0
)
{
/*
* Find the next NUMA cell described in the xend output
*/
cur
=
strstr
(
cur
,
"node"
);
if
(
cur
==
NULL
)
break
;
cur
+=
4
;
cell
=
parseNumber
(
&
cur
);
if
(
cell
<
0
)
goto
parse_error
;
skipSpaces
(
&
cur
);
if
(
*
cur
!=
':'
)
goto
parse_error
;
cur
++
;
skipSpaces
(
&
cur
);
if
(
!
strncmp
(
cur
,
"no cpus"
,
7
))
{
nb_cpus
=
0
;
for
(
cpu
=
0
;
cpu
<
maxcpu
;
cpu
++
)
cpuset
[
cpu
]
=
0
;
}
else
{
nb_cpus
=
virParseCpuSet
(
conn
,
&
cur
,
'n'
,
cpuset
,
maxcpu
);
if
(
nb_cpus
<
0
)
goto
error
;
}
/*
* add xml for all cpus associated with that cell
*/
ret
=
virBufferVSprintf
(
xml
,
"\
<cell id='%d'>
\n
\
<cpus num='%d'>
\n
"
,
cell
,
nb_cpus
);
#ifdef STANDALONE
{
char
*
dump
;
dump
=
saveCpuSet
(
conn
,
cpuset
,
maxcpu
);
if
(
dump
!=
NULL
)
{
virBufferVSprintf
(
xml
,
" <dump>%s</dump>
\n
"
,
dump
);
free
(
dump
);
}
else
{
virBufferVSprintf
(
xml
,
" <error>%s</error>
\n
"
,
"Failed to dump CPU set"
);
}
}
#endif
if
(
ret
<
0
)
goto
memory_error
;
for
(
cpu
=
0
;
cpu
<
maxcpu
;
cpu
++
)
{
if
(
cpuset
[
cpu
]
==
1
)
{
ret
=
virBufferVSprintf
(
xml
,
"\
<cpu id='%d'/>
\n
"
,
cpu
);
if
(
ret
<
0
)
goto
memory_error
;
}
}
ret
=
virBufferAdd
(
xml
,
"\
</cpus>
\n
\
</cell>
\n
"
,
-
1
);
if
(
ret
<
0
)
goto
memory_error
;
}
free
(
cpuset
);
return
(
0
);
parse_error:
virXMLError
(
conn
,
VIR_ERR_XEN_CALL
,
_
(
"topology syntax error"
),
0
);
error:
if
(
cpuset
!=
NULL
)
free
(
cpuset
);
return
(
-
1
);
memory_error:
if
(
cpuset
!=
NULL
)
free
(
cpuset
);
virXMLError
(
conn
,
VIR_ERR_NO_MEMORY
,
_
(
"allocate buffer"
),
0
);
return
(
-
1
);
}
/************************************************************************
* *
* Wrappers around libxml2 XPath specific functions *
* *
************************************************************************/
/**
* virXPathString:
* @xpath: the XPath string to evaluate
...
...
@@ -271,6 +628,12 @@ virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
return
(
ret
);
}
/************************************************************************
* *
* Converter functions to go from the XML tree to an S-Expr for Xen *
* *
************************************************************************/
/**
* virtDomainParseXMLGraphicsDescImage:
* @conn: pointer to the hypervisor connection
...
...
@@ -1167,6 +1530,36 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
}
virBufferVSprintf
(
&
buf
,
"(vcpus %u)"
,
vcpus
);
str
=
virXPathString
(
"string(/domain/vcpu/@cpuset)"
,
ctxt
);
if
(
str
!=
NULL
)
{
int
maxcpu
=
xenNbCpus
(
conn
);
char
*
cpuset
=
NULL
;
char
*
ranges
=
NULL
;
const
char
*
cur
=
str
;
/*
* Parse the CPUset attribute given in libvirt format and reserialize
* it in a range format guaranteed to be understood by Xen.
*/
if
(
maxcpu
>
0
)
{
cpuset
=
malloc
(
maxcpu
*
sizeof
(
char
));
if
(
cpuset
!=
NULL
)
{
res
=
virParseCpuSet
(
conn
,
&
cur
,
0
,
cpuset
,
maxcpu
);
if
(
res
>
0
)
{
ranges
=
saveCpuSet
(
conn
,
cpuset
,
maxcpu
);
if
(
ranges
!=
NULL
)
{
virBufferVSprintf
(
&
buf
,
"(cpus '%s')"
,
ranges
);
free
(
ranges
);
}
}
free
(
cpuset
);
}
else
{
virXMLError
(
conn
,
VIR_ERR_NO_MEMORY
,
xmldesc
,
0
);
}
}
free
(
str
);
}
str
=
virXPathString
(
"string(/domain/uuid[1])"
,
ctxt
);
if
(
str
!=
NULL
)
{
virBufferVSprintf
(
&
buf
,
"(uuid '%s')"
,
str
);
...
...
src/xml.h
浏览文件 @
cfb192ad
...
...
@@ -7,6 +7,7 @@
#include "libvirt/libvirt.h"
#include "internal.h"
#include "buf.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
...
...
@@ -31,9 +32,28 @@ int virXPathNodeSet (const char *xpath,
xmlXPathContextPtr
ctxt
,
xmlNodePtr
**
list
);
char
*
virDomainParseXMLDesc
(
virConnectPtr
conn
,
const
char
*
xmldesc
,
char
**
name
,
int
xendConfigVersion
);
char
*
virParseXMLDevice
(
virConnectPtr
conn
,
const
char
*
xmldesc
,
int
hvm
,
int
xendConfigVersion
);
int
virDomainXMLDevID
(
virDomainPtr
domain
,
const
char
*
xmldesc
,
char
*
class
,
char
*
ref
,
int
ref_len
);
int
virParseXenCpuTopology
(
virConnectPtr
conn
,
virBufferPtr
xml
,
const
char
*
str
,
int
maxcpu
);
int
virParseCpuSet
(
virConnectPtr
conn
,
const
char
**
str
,
char
sep
,
char
*
cpuset
,
int
maxcpu
);
char
*
virDomainParseXMLDesc
(
virConnectPtr
conn
,
const
char
*
xmldesc
,
char
**
name
,
int
xendConfigVersion
);
char
*
virParseXMLDevice
(
virConnectPtr
conn
,
const
char
*
xmldesc
,
int
hvm
,
int
xendConfigVersion
);
int
virDomainXMLDevID
(
virDomainPtr
domain
,
const
char
*
xmldesc
,
char
*
class
,
char
*
ref
,
int
ref_len
);
#ifdef __cplusplus
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录