Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
a87420ae
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a87420ae
编写于
10月 22, 2007
作者:
D
Daniel Veillard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
* src/xend_internal.c: update to cpuset parsing code for NUMA
Daniel
上级
d620b00f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
347 addition
and
145 deletion
+347
-145
ChangeLog
ChangeLog
+4
-0
src/xend_internal.c
src/xend_internal.c
+343
-145
未找到文件。
ChangeLog
浏览文件 @
a87420ae
Mon Oct 22 15:05:30 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/xend_internal.c: update to cpuset parsing code for NUMA
Fri Oct 19 17:08:08 CEST 2007 Daniel Veillard <veillard@redhat.com>
Fri Oct 19 17:08:08 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/Makefile.am: fix tst build rule
* src/Makefile.am: fix tst build rule
...
...
src/xend_internal.c
浏览文件 @
a87420ae
...
@@ -1896,24 +1896,349 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
...
@@ -1896,24 +1896,349 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
}
}
/**
/**
* getNumber:
* skipSpaces:
* @pointer: pointer to string beginning with numerical characters
* @str: pointer to the char pointer used
* @result: pointer to integer for storing the numerical result
*
*
* Internal routine extracting a number from the beginning of a string
* 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
*
*
* Returns the number of characters that were extracted as digits
* Parse a number
* or -1 if no digits were found.
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
*/
static
int
static
int
getNumber
(
const
char
*
pointer
,
int
*
result
)
{
parseNumber
(
const
char
**
str
)
{
int
len
=
0
;
int
ret
=
0
;
while
(
isdigit
(
*
(
pointer
+
len
)))
const
char
*
cur
=
*
str
;
len
++
;
if
(
len
==
0
)
if
((
*
cur
<
'0'
)
||
(
*
cur
>
'9'
))
return
-
1
;
return
(
-
1
);
*
(
result
)
=
atoi
(
pointer
);
return
(
len
);
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
);
}
}
/**
/**
...
@@ -1929,21 +2254,9 @@ static int
...
@@ -1929,21 +2254,9 @@ static int
sexpr_to_xend_topology_xml
(
virConnectPtr
conn
,
struct
sexpr
*
root
,
virBufferPtr
xml
)
sexpr_to_xend_topology_xml
(
virConnectPtr
conn
,
struct
sexpr
*
root
,
virBufferPtr
xml
)
{
{
const
char
*
nodeToCpu
;
const
char
*
nodeToCpu
;
const
char
*
offset
;
int
cellNum
;
int
numCells
=
0
;
int
numCells
=
0
;
int
numCpus
;
int
numCpus
;
int
cellCpuCount
=
0
;
int
nodeCpuCount
=
0
;
int
start
;
int
finish
;
int
r
;
int
r
;
int
i
;
int
len
;
int
cpuNum
;
int
*
cpuIdsPtr
=
NULL
;
int
*
iCpuIdsPtr
=
NULL
;
char
next
;
nodeToCpu
=
sexpr_node
(
root
,
"node/node_to_cpu"
);
nodeToCpu
=
sexpr_node
(
root
,
"node/node_to_cpu"
);
if
(
nodeToCpu
==
NULL
)
{
if
(
nodeToCpu
==
NULL
)
{
...
@@ -1955,134 +2268,21 @@ sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr
...
@@ -1955,134 +2268,21 @@ sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr
numCells
=
sexpr_int
(
root
,
"node/nr_nodes"
);
numCells
=
sexpr_int
(
root
,
"node/nr_nodes"
);
numCpus
=
sexpr_int
(
root
,
"node/nr_cpus"
);
numCpus
=
sexpr_int
(
root
,
"node/nr_cpus"
);
/* array for holding all cpu numbers associated with a single cell.
* Should never need more than numCpus (which is total number of
* cpus for the node)
*/
cpuIdsPtr
=
iCpuIdsPtr
=
malloc
(
numCpus
*
sizeof
(
int
));
if
(
cpuIdsPtr
==
NULL
)
{
goto
vir_buffer_failed
;
}
/* start filling in xml */
/* start filling in xml */
r
=
virBufferVSprintf
(
xml
,
r
=
virBufferVSprintf
(
xml
,
"\
"\
<topology>
\n
\
<topology>
\n
\
<cells num='%d'>
\n
"
,
<cells num='%d'>
\n
"
,
numCells
);
numCells
);
if
(
r
==
-
1
)
goto
vir_buffer_failed
;
if
(
r
<
0
)
goto
vir_buffer_failed
;
offset
=
nodeToCpu
;
/* now iterate through all cells and find associated cpu ids */
/* example of string being parsed: "node0:0-3,7,9-10\n node1:11-14\n" */
while
((
offset
=
strstr
(
offset
,
"node"
))
!=
NULL
)
{
cpuIdsPtr
=
iCpuIdsPtr
;
cellCpuCount
=
0
;
offset
+=
4
;
if
((
len
=
getNumber
(
offset
,
&
cellNum
))
<
0
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
offset
+=
len
;
if
(
*
(
offset
)
!=
':'
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
offset
++
;
/* get list of cpus associated w/ single cell */
while
(
1
)
{
len
=
getNumber
(
offset
,
&
cpuNum
);
if
(
len
<
0
)
{
if
(
!
strncmp
(
offset
,
"no cpus"
,
7
)){
*
(
cpuIdsPtr
++
)
=
-
1
;
break
;
}
else
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
"topology string syntax error"
);
goto
error
;
}
}
offset
+=
len
;
next
=
*
(
offset
);
if
(
next
==
'-'
)
{
offset
++
;
start
=
cpuNum
;
if
((
len
=
getNumber
(
offset
,
&
finish
))
<
0
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
if
(
start
>
finish
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
for
(
i
=
start
;
i
<=
finish
;
i
++
)
{
nodeCpuCount
++
;
if
(
nodeCpuCount
>
numCpus
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
"conflicting cpu counts"
);
goto
error
;
}
*
(
cpuIdsPtr
++
)
=
i
;
cellCpuCount
++
;
}
offset
+=
len
;
next
=
*
(
offset
);
offset
++
;
if
(
next
==
','
)
{
continue
;
}
else
if
((
next
==
'\\'
)
||
(
next
==
'\0'
))
{
break
;
}
else
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
}
else
{
/* add the single number */
if
(
nodeCpuCount
>=
numCpus
)
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
"conflicting cpu counts"
);
goto
error
;
}
*
(
cpuIdsPtr
++
)
=
cpuNum
;
cellCpuCount
++
;
nodeCpuCount
++
;
if
(
next
==
','
)
{
offset
++
;
continue
;
}
else
if
((
next
==
'\\'
)
||
(
next
==
'\0'
))
{
break
;
}
else
{
virXendError
(
conn
,
VIR_ERR_XEN_CALL
,
" topology string syntax error"
);
goto
error
;
}
}
}
/* add xml for all cpus associated with one cell */
r
=
parseTopology
(
conn
,
xml
,
nodeToCpu
,
numCpus
);
r
=
virBufferVSprintf
(
xml
,
"\
if
(
r
<
0
)
goto
error
;
<cell id='%d'>
\n
\
<cpus num='%d'>
\n
"
,
cellNum
,
cellCpuCount
);
if
(
r
==
-
1
)
goto
vir_buffer_failed
;
for
(
i
=
0
;
i
<
cellCpuCount
;
i
++
)
{
if
(
*
(
iCpuIdsPtr
+
i
)
==
-
1
)
break
;
r
=
virBufferVSprintf
(
xml
,
"\
<cpu id='%d'/>
\n
"
,
*
(
iCpuIdsPtr
+
i
));
if
(
r
==
-
1
)
goto
vir_buffer_failed
;
}
r
=
virBufferAdd
(
xml
,
"\
</cpus>
\n
\
</cell>
\n
"
,
-
1
);
if
(
r
==
-
1
)
goto
vir_buffer_failed
;
}
r
=
virBufferAdd
(
xml
,
"\
r
=
virBufferAdd
(
xml
,
"\
</cells>
\n
\
</cells>
\n
\
</topology>
\n
"
,
-
1
);
</topology>
\n
"
,
-
1
);
if
(
r
==
-
1
)
goto
vir_buffer_failed
;
if
(
r
<
0
)
goto
vir_buffer_failed
;
free
(
iCpuIdsPtr
);
return
(
0
);
return
(
0
);
...
@@ -2090,8 +2290,6 @@ vir_buffer_failed:
...
@@ -2090,8 +2290,6 @@ vir_buffer_failed:
virXendError
(
conn
,
VIR_ERR_NO_MEMORY
,
_
(
"allocate new buffer"
));
virXendError
(
conn
,
VIR_ERR_NO_MEMORY
,
_
(
"allocate new buffer"
));
error:
error:
if
(
iCpuIdsPtr
)
free
(
iCpuIdsPtr
);
return
(
-
1
);
return
(
-
1
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录