Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
6d7d465a
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看板
提交
6d7d465a
编写于
7月 16, 2009
作者:
C
Cole Robinson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
storage: Move most of the FS creation functions to common backend.
These will be used by other pool cloning implementations.
上级
1b16bf4e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
436 addition
and
418 deletion
+436
-418
src/storage_backend.c
src/storage_backend.c
+413
-0
src/storage_backend.h
src/storage_backend.h
+16
-0
src/storage_backend_fs.c
src/storage_backend_fs.c
+7
-418
未找到文件。
src/storage_backend.c
浏览文件 @
6d7d465a
...
...
@@ -95,6 +95,419 @@ static virStorageBackendPtr backends[] = {
NULL
};
static
int
track_allocation_progress
=
0
;
enum
{
TOOL_QEMU_IMG
,
TOOL_KVM_IMG
,
TOOL_QCOW_CREATE
,
};
int
virStorageBackendCreateRaw
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
int
fd
=
-
1
;
int
inputfd
=
-
1
;
int
ret
=
-
1
;
unsigned
long
long
remain
;
char
*
buf
=
NULL
;
if
((
fd
=
open
(
vol
->
target
.
path
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
vol
->
target
.
perms
.
mode
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot create path '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
if
(
inputvol
)
{
if
((
inputfd
=
open
(
inputvol
->
target
.
path
,
O_RDONLY
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"could not open input path '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
}
/* Seek to the final size, so the capacity is available upfront
* for progress reporting */
if
(
ftruncate
(
fd
,
vol
->
capacity
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot extend file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
remain
=
vol
->
allocation
;
if
(
inputfd
!=
-
1
)
{
int
amtread
=
-
1
;
size_t
bytes
=
1024
*
1024
;
char
zerobuf
[
512
];
bzero
(
&
zerobuf
,
sizeof
(
zerobuf
));
if
(
VIR_ALLOC_N
(
buf
,
bytes
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
while
(
amtread
!=
0
)
{
int
amtleft
;
if
(
remain
<
bytes
)
bytes
=
remain
;
if
((
amtread
=
saferead
(
inputfd
,
buf
,
bytes
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"failed reading from file '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
remain
-=
amtread
;
/* Loop over amt read in 512 byte increments, looking for sparse
* blocks */
amtleft
=
amtread
;
do
{
int
interval
=
((
512
>
amtleft
)
?
amtleft
:
512
);
int
offset
=
amtread
-
amtleft
;
if
(
memcmp
(
buf
+
offset
,
zerobuf
,
interval
)
==
0
)
{
if
(
lseek
(
fd
,
interval
,
SEEK_CUR
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot extend file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
else
if
(
safewrite
(
fd
,
buf
+
offset
,
interval
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"failed writing to file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
while
((
amtleft
-=
512
)
>
0
);
}
}
if
(
remain
)
{
if
(
track_allocation_progress
)
{
while
(
remain
)
{
/* Allocate in chunks of 512MiB: big-enough chunk
* size and takes approx. 9s on ext3. A progress
* update every 9s is a fair-enough trade-off
*/
unsigned
long
long
bytes
=
512
*
1024
*
1024
;
int
r
;
if
(
bytes
>
remain
)
bytes
=
remain
;
if
((
r
=
safezero
(
fd
,
0
,
vol
->
allocation
-
remain
,
bytes
))
!=
0
)
{
virReportSystemError
(
conn
,
r
,
_
(
"cannot fill file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
remain
-=
bytes
;
}
}
else
{
/* No progress bars to be shown */
int
r
;
if
((
r
=
safezero
(
fd
,
0
,
0
,
remain
))
!=
0
)
{
virReportSystemError
(
conn
,
r
,
_
(
"cannot fill file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
}
if
(
close
(
fd
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot close file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
fd
=
-
1
;
if
(
inputfd
!=
-
1
&&
close
(
inputfd
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot close file '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
inputfd
=
-
1
;
ret
=
0
;
cleanup:
if
(
fd
!=
-
1
)
close
(
fd
);
if
(
inputfd
!=
-
1
)
close
(
inputfd
);
VIR_FREE
(
buf
);
return
ret
;
}
static
int
virStorageBackendCreateQemuImg
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
char
size
[
100
];
char
*
create_tool
;
short
use_kvmimg
;
const
char
*
type
=
virStorageVolFormatFileSystemTypeToString
(
vol
->
target
.
format
);
const
char
*
backingType
=
vol
->
backingStore
.
path
?
virStorageVolFormatFileSystemTypeToString
(
vol
->
backingStore
.
format
)
:
NULL
;
const
char
*
inputBackingPath
=
(
inputvol
?
inputvol
->
backingStore
.
path
:
NULL
);
const
char
*
inputPath
=
inputvol
?
inputvol
->
target
.
path
:
NULL
;
/* Treat input block devices as 'raw' format */
const
char
*
inputType
=
inputPath
?
virStorageVolFormatFileSystemTypeToString
(
inputvol
->
type
==
VIR_STORAGE_VOL_BLOCK
?
VIR_STORAGE_VOL_FILE_RAW
:
inputvol
->
target
.
format
)
:
NULL
;
const
char
**
imgargv
;
const
char
*
imgargvnormal
[]
=
{
NULL
,
"create"
,
"-f"
,
type
,
vol
->
target
.
path
,
size
,
NULL
,
};
/* Extra NULL fields are for including "backingType" when using
* kvm-img. It's -F backingType
*/
const
char
*
imgargvbacking
[]
=
{
NULL
,
"create"
,
"-f"
,
type
,
"-b"
,
vol
->
backingStore
.
path
,
vol
->
target
.
path
,
size
,
NULL
,
NULL
,
NULL
};
const
char
*
convargv
[]
=
{
NULL
,
"convert"
,
"-f"
,
inputType
,
"-O"
,
type
,
inputPath
,
vol
->
target
.
path
,
NULL
,
};
if
(
type
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol type %d"
),
vol
->
target
.
format
);
return
-
1
;
}
if
(
inputvol
&&
inputType
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol type %d"
),
inputvol
->
target
.
format
);
return
-
1
;
}
if
(
vol
->
backingStore
.
path
)
{
/* XXX: Not strictly required: qemu-img has an option a different
* backing store, not really sure what use it serves though, and it
* may cause issues with lvm. Untested essentially.
*/
if
(
inputvol
&&
(
!
inputBackingPath
||
STRNEQ
(
inputBackingPath
,
vol
->
backingStore
.
path
)))
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"a different backing store can not "
"be specified."
));
return
-
1
;
}
if
(
backingType
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol backing store type %d"
),
vol
->
backingStore
.
format
);
return
-
1
;
}
if
(
access
(
vol
->
backingStore
.
path
,
R_OK
)
!=
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"inaccessible backing store volume %s"
),
vol
->
backingStore
.
path
);
return
-
1
;
}
}
if
((
create_tool
=
virFindFileInPath
(
"kvm-img"
))
!=
NULL
)
use_kvmimg
=
1
;
else
if
((
create_tool
=
virFindFileInPath
(
"qemu-img"
))
!=
NULL
)
use_kvmimg
=
0
;
else
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unable to find kvm-img or qemu-img"
));
return
-
1
;
}
if
(
inputvol
)
{
convargv
[
0
]
=
create_tool
;
imgargv
=
convargv
;
}
else
if
(
vol
->
backingStore
.
path
)
{
imgargvbacking
[
0
]
=
create_tool
;
if
(
use_kvmimg
)
{
imgargvbacking
[
6
]
=
"-F"
;
imgargvbacking
[
7
]
=
backingType
;
imgargvbacking
[
8
]
=
vol
->
target
.
path
;
imgargvbacking
[
9
]
=
size
;
}
imgargv
=
imgargvbacking
;
}
else
{
imgargvnormal
[
0
]
=
create_tool
;
imgargv
=
imgargvnormal
;
}
/* Size in KB */
snprintf
(
size
,
sizeof
(
size
),
"%llu"
,
vol
->
capacity
/
1024
);
if
(
virRun
(
conn
,
imgargv
,
NULL
)
<
0
)
{
VIR_FREE
(
imgargv
[
0
]);
return
-
1
;
}
VIR_FREE
(
imgargv
[
0
]);
return
0
;
}
/*
* Xen removed the fully-functional qemu-img, and replaced it
* with a partially functional qcow-create. Go figure ??!?
*/
static
int
virStorageBackendCreateQcowCreate
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
char
size
[
100
];
const
char
*
imgargv
[
4
];
if
(
inputvol
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"cannot copy from volume with qcow-create"
));
return
-
1
;
}
if
(
vol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_QCOW2
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unsupported storage vol type %d"
),
vol
->
target
.
format
);
return
-
1
;
}
if
(
vol
->
backingStore
.
path
!=
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_NO_SUPPORT
,
_
(
"copy-on-write image not supported with "
"qcow-create"
));
return
-
1
;
}
/* Size in MB - yes different units to qemu-img :-( */
snprintf
(
size
,
sizeof
(
size
),
"%llu"
,
vol
->
capacity
/
1024
/
1024
);
imgargv
[
0
]
=
virFindFileInPath
(
"qcow-create"
);
imgargv
[
1
]
=
size
;
imgargv
[
2
]
=
vol
->
target
.
path
;
imgargv
[
3
]
=
NULL
;
if
(
virRun
(
conn
,
imgargv
,
NULL
)
<
0
)
{
VIR_FREE
(
imgargv
[
0
]);
return
-
1
;
}
VIR_FREE
(
imgargv
[
0
]);
return
0
;
}
createFile
virStorageBackendFSImageToolTypeToFunc
(
virConnectPtr
conn
,
int
tool_type
)
{
switch
(
tool_type
)
{
case
TOOL_KVM_IMG
:
case
TOOL_QEMU_IMG
:
return
virStorageBackendCreateQemuImg
;
case
TOOL_QCOW_CREATE
:
return
virStorageBackendCreateQcowCreate
;
default:
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Unknown file create tool type '%d'."
),
tool_type
);
}
return
NULL
;
}
int
virStorageBackendFindFSImageTool
(
char
**
tool
)
{
int
tool_type
=
-
1
;
char
*
tmp
=
NULL
;
if
((
tmp
=
virFindFileInPath
(
"kvm-img"
))
!=
NULL
)
{
tool_type
=
TOOL_KVM_IMG
;
}
else
if
((
tmp
=
virFindFileInPath
(
"qemu-img"
))
!=
NULL
)
{
tool_type
=
TOOL_QEMU_IMG
;
}
else
if
((
tmp
=
virFindFileInPath
(
"qcow-create"
))
!=
NULL
)
{
tool_type
=
TOOL_QCOW_CREATE
;
}
if
(
tool
)
*
tool
=
tmp
;
else
VIR_FREE
(
tmp
);
return
tool_type
;
}
createFile
virStorageBackendGetBuildVolFromFunction
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
int
tool_type
;
if
(
!
inputvol
)
return
NULL
;
/* If either volume is a non-raw file vol, we need to use an external
* tool for converting
*/
if
((
vol
->
type
==
VIR_STORAGE_VOL_FILE
&&
vol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_RAW
)
||
(
inputvol
->
type
==
VIR_STORAGE_VOL_FILE
&&
inputvol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_RAW
))
{
if
((
tool_type
=
virStorageBackendFindFSImageTool
(
NULL
))
!=
-
1
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"creation of non-raw file images is "
"not supported without qemu-img."
));
return
NULL
;
}
return
virStorageBackendFSImageToolTypeToFunc
(
conn
,
tool_type
);
}
return
virStorageBackendCreateRaw
;
}
#if defined(UDEVADM) || defined(UDEVSETTLE)
void
virWaitForDevices
(
virConnectPtr
conn
)
...
...
src/storage_backend.h
浏览文件 @
6d7d465a
...
...
@@ -40,6 +40,22 @@ typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObj
typedef
int
(
*
virStorageBackendDeleteVol
)(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
virStorageVolDefPtr
vol
,
unsigned
int
flags
);
typedef
int
(
*
virStorageBackendBuildVolFrom
)(
virConnectPtr
conn
,
virStorageVolDefPtr
origvol
,
virStorageVolDefPtr
newvol
,
unsigned
int
flags
);
typedef
int
(
*
createFile
)(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
);
/* File creation/cloning functions used for cloning between backends */
int
virStorageBackendCreateRaw
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
);
createFile
virStorageBackendGetBuildVolFromFunction
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
);
int
virStorageBackendFindFSImageTool
(
char
**
tool
);
createFile
virStorageBackendFSImageToolTypeToFunc
(
virConnectPtr
conn
,
int
tool_type
);
typedef
struct
_virStorageBackend
virStorageBackend
;
typedef
virStorageBackend
*
virStorageBackendPtr
;
...
...
src/storage_backend_fs.c
浏览文件 @
6d7d465a
...
...
@@ -55,12 +55,6 @@ enum {
BACKING_STORE_ERROR
,
};
enum
{
TOOL_QEMU_IMG
,
TOOL_KVM_IMG
,
TOOL_QCOW_CREATE
,
};
static
int
cowGetBackingStore
(
virConnectPtr
,
char
**
,
const
unsigned
char
*
,
size_t
);
static
int
qcowXGetBackingStore
(
virConnectPtr
,
char
**
,
...
...
@@ -68,12 +62,6 @@ static int qcowXGetBackingStore(virConnectPtr, char **,
static
int
vmdk4GetBackingStore
(
virConnectPtr
,
char
**
,
const
unsigned
char
*
,
size_t
);
typedef
int
(
*
createFile
)(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
);
static
int
track_allocation_progress
=
0
;
/* Either 'magic' or 'extension' *must* be provided */
struct
FileTypeInfo
{
int
type
;
/* One of the constants above */
...
...
@@ -1018,157 +1006,6 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn,
return
0
;
}
static
int
createRaw
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
int
fd
=
-
1
;
int
inputfd
=
-
1
;
int
ret
=
-
1
;
unsigned
long
long
remain
;
char
*
buf
=
NULL
;
if
((
fd
=
open
(
vol
->
target
.
path
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
vol
->
target
.
perms
.
mode
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot create path '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
if
(
inputvol
)
{
if
((
inputfd
=
open
(
inputvol
->
target
.
path
,
O_RDONLY
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"could not open input path '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
}
/* Seek to the final size, so the capacity is available upfront
* for progress reporting */
if
(
ftruncate
(
fd
,
vol
->
capacity
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot extend file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
remain
=
vol
->
allocation
;
if
(
inputfd
!=
-
1
)
{
int
amtread
=
-
1
;
size_t
bytes
=
1024
*
1024
;
char
zerobuf
[
512
];
bzero
(
&
zerobuf
,
sizeof
(
zerobuf
));
if
(
VIR_ALLOC_N
(
buf
,
bytes
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
while
(
amtread
!=
0
)
{
int
amtleft
;
if
(
remain
<
bytes
)
bytes
=
remain
;
if
((
amtread
=
saferead
(
inputfd
,
buf
,
bytes
))
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"failed reading from file '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
remain
-=
amtread
;
/* Loop over amt read in 512 byte increments, looking for sparse
* blocks */
amtleft
=
amtread
;
do
{
int
interval
=
((
512
>
amtleft
)
?
amtleft
:
512
);
int
offset
=
amtread
-
amtleft
;
if
(
memcmp
(
buf
+
offset
,
zerobuf
,
interval
)
==
0
)
{
if
(
lseek
(
fd
,
interval
,
SEEK_CUR
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot extend file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
else
if
(
safewrite
(
fd
,
buf
+
offset
,
interval
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"failed writing to file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
while
((
amtleft
-=
512
)
>
0
);
}
}
/* Pre-allocate any data if requested */
/* XXX slooooooooooooooooow on non-extents-based file systems */
if
(
remain
)
{
if
(
track_allocation_progress
)
{
while
(
remain
)
{
/* Allocate in chunks of 512MiB: big-enough chunk
* size and takes approx. 9s on ext3. A progress
* update every 9s is a fair-enough trade-off
*/
unsigned
long
long
bytes
=
512
*
1024
*
1024
;
int
r
;
if
(
bytes
>
remain
)
bytes
=
remain
;
if
((
r
=
safezero
(
fd
,
0
,
vol
->
allocation
-
remain
,
bytes
))
!=
0
)
{
virReportSystemError
(
conn
,
r
,
_
(
"cannot fill file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
remain
-=
bytes
;
}
}
else
{
/* No progress bars to be shown */
int
r
;
if
((
r
=
safezero
(
fd
,
0
,
0
,
remain
))
!=
0
)
{
virReportSystemError
(
conn
,
r
,
_
(
"cannot fill file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
}
}
if
(
close
(
fd
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot close file '%s'"
),
vol
->
target
.
path
);
goto
cleanup
;
}
fd
=
-
1
;
if
(
inputfd
!=
-
1
&&
close
(
inputfd
)
<
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"cannot close file '%s'"
),
inputvol
->
target
.
path
);
goto
cleanup
;
}
inputfd
=
-
1
;
ret
=
0
;
cleanup:
if
(
fd
!=
-
1
)
close
(
fd
);
if
(
inputfd
!=
-
1
)
close
(
inputfd
);
VIR_FREE
(
buf
);
return
ret
;
}
static
int
createFileDir
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
...
...
@@ -1189,257 +1026,6 @@ static int createFileDir(virConnectPtr conn,
return
0
;
}
static
int
createQemuImg
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
char
size
[
100
];
char
*
create_tool
;
short
use_kvmimg
;
const
char
*
type
=
virStorageVolFormatFileSystemTypeToString
(
vol
->
target
.
format
);
const
char
*
backingType
=
vol
->
backingStore
.
path
?
virStorageVolFormatFileSystemTypeToString
(
vol
->
backingStore
.
format
)
:
NULL
;
const
char
*
inputBackingPath
=
(
inputvol
?
inputvol
->
backingStore
.
path
:
NULL
);
const
char
*
inputPath
=
inputvol
?
inputvol
->
target
.
path
:
NULL
;
/* Treat input block devices as 'raw' format */
const
char
*
inputType
=
inputPath
?
virStorageVolFormatFileSystemTypeToString
(
inputvol
->
type
==
VIR_STORAGE_VOL_BLOCK
?
VIR_STORAGE_VOL_FILE_RAW
:
inputvol
->
target
.
format
)
:
NULL
;
const
char
**
imgargv
;
const
char
*
imgargvnormal
[]
=
{
NULL
,
"create"
,
"-f"
,
type
,
vol
->
target
.
path
,
size
,
NULL
,
};
/* Extra NULL fields are for including "backingType" when using
* kvm-img. It's -F backingType
*/
const
char
*
imgargvbacking
[]
=
{
NULL
,
"create"
,
"-f"
,
type
,
"-b"
,
vol
->
backingStore
.
path
,
vol
->
target
.
path
,
size
,
NULL
,
NULL
,
NULL
};
const
char
*
convargv
[]
=
{
NULL
,
"convert"
,
"-f"
,
inputType
,
"-O"
,
type
,
inputPath
,
vol
->
target
.
path
,
NULL
,
};
if
(
type
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol type %d"
),
vol
->
target
.
format
);
return
-
1
;
}
if
(
inputvol
&&
inputType
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol type %d"
),
inputvol
->
target
.
format
);
return
-
1
;
}
if
(
vol
->
backingStore
.
path
)
{
/* XXX: Not strictly required: qemu-img has an option a different
* backing store, not really sure what use it serves though, and it
* may cause issues with lvm. Untested essentially.
*/
if
(
inputvol
&&
(
!
inputBackingPath
||
STRNEQ
(
inputBackingPath
,
vol
->
backingStore
.
path
)))
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"a different backing store can not "
"be specified."
));
return
-
1
;
}
if
(
backingType
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unknown storage vol backing store type %d"
),
vol
->
backingStore
.
format
);
return
-
1
;
}
if
(
access
(
vol
->
backingStore
.
path
,
R_OK
)
!=
0
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"inaccessible backing store volume %s"
),
vol
->
backingStore
.
path
);
return
-
1
;
}
}
if
((
create_tool
=
virFindFileInPath
(
"kvm-img"
))
!=
NULL
)
use_kvmimg
=
1
;
else
if
((
create_tool
=
virFindFileInPath
(
"qemu-img"
))
!=
NULL
)
use_kvmimg
=
0
;
else
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unable to find kvm-img or qemu-img"
));
return
-
1
;
}
if
(
inputvol
)
{
convargv
[
0
]
=
create_tool
;
imgargv
=
convargv
;
}
else
if
(
vol
->
backingStore
.
path
)
{
imgargvbacking
[
0
]
=
create_tool
;
if
(
use_kvmimg
)
{
imgargvbacking
[
6
]
=
"-F"
;
imgargvbacking
[
7
]
=
backingType
;
imgargvbacking
[
8
]
=
vol
->
target
.
path
;
imgargvbacking
[
9
]
=
size
;
}
imgargv
=
imgargvbacking
;
}
else
{
imgargvnormal
[
0
]
=
create_tool
;
imgargv
=
imgargvnormal
;
}
/* Size in KB */
snprintf
(
size
,
sizeof
(
size
),
"%llu"
,
vol
->
capacity
/
1024
);
if
(
virRun
(
conn
,
imgargv
,
NULL
)
<
0
)
{
VIR_FREE
(
imgargv
[
0
]);
return
-
1
;
}
VIR_FREE
(
imgargv
[
0
]);
return
0
;
}
/*
* Xen removed the fully-functional qemu-img, and replaced it
* with a partially functional qcow-create. Go figure ??!?
*/
static
int
createQemuCreate
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
char
size
[
100
];
const
char
*
imgargv
[
4
];
if
(
inputvol
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"cannot copy from volume with qcow-create"
));
return
-
1
;
}
if
(
vol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_QCOW2
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unsupported storage vol type %d"
),
vol
->
target
.
format
);
return
-
1
;
}
if
(
vol
->
backingStore
.
path
!=
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_NO_SUPPORT
,
_
(
"copy-on-write image not supported with "
"qcow-create"
));
return
-
1
;
}
/* Size in MB - yes different units to qemu-img :-( */
snprintf
(
size
,
sizeof
(
size
),
"%llu"
,
vol
->
capacity
/
1024
/
1024
);
imgargv
[
0
]
=
virFindFileInPath
(
"qcow-create"
);
imgargv
[
1
]
=
size
;
imgargv
[
2
]
=
vol
->
target
.
path
;
imgargv
[
3
]
=
NULL
;
if
(
virRun
(
conn
,
imgargv
,
NULL
)
<
0
)
{
VIR_FREE
(
imgargv
[
0
]);
return
-
1
;
}
VIR_FREE
(
imgargv
[
0
]);
return
0
;
}
static
createFile
toolTypeToFunction
(
virConnectPtr
conn
,
int
tool_type
)
{
switch
(
tool_type
)
{
case
TOOL_KVM_IMG
:
case
TOOL_QEMU_IMG
:
return
createQemuImg
;
case
TOOL_QCOW_CREATE
:
return
createQemuCreate
;
default:
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Unknown file create tool type '%d'."
),
tool_type
);
}
return
NULL
;
}
static
int
findImageTool
(
char
**
tool
)
{
int
tool_type
=
-
1
;
char
*
tmp
=
NULL
;
if
((
tmp
=
virFindFileInPath
(
"kvm-img"
))
!=
NULL
)
{
tool_type
=
TOOL_KVM_IMG
;
}
else
if
((
tmp
=
virFindFileInPath
(
"qemu-img"
))
!=
NULL
)
{
tool_type
=
TOOL_QEMU_IMG
;
}
else
if
((
tmp
=
virFindFileInPath
(
"qcow-create"
))
!=
NULL
)
{
tool_type
=
TOOL_QCOW_CREATE
;
}
if
(
tool
)
*
tool
=
tmp
;
else
VIR_FREE
(
tmp
);
return
tool_type
;
}
static
createFile
buildVolFromFunction
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
virStorageVolDefPtr
inputvol
)
{
int
tool_type
;
if
(
!
inputvol
)
return
NULL
;
/* If either volume is a non-raw file vol, we need to use an external
* tool for converting
*/
if
((
vol
->
type
==
VIR_STORAGE_VOL_FILE
&&
vol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_RAW
)
||
(
inputvol
->
type
==
VIR_STORAGE_VOL_FILE
&&
inputvol
->
target
.
format
!=
VIR_STORAGE_VOL_FILE_RAW
))
{
if
((
tool_type
=
findImageTool
(
NULL
))
!=
-
1
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"creation of non-raw file images is "
"not supported without qemu-img."
));
return
NULL
;
}
return
toolTypeToFunction
(
conn
,
tool_type
);
}
return
createRaw
;
}
static
int
_virStorageBackendFileSystemVolBuild
(
virConnectPtr
conn
,
virStorageVolDefPtr
vol
,
...
...
@@ -1450,15 +1036,18 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
int
tool_type
;
if
(
inputvol
)
{
create_func
=
buildVolFromFunction
(
conn
,
vol
,
inputvol
);
create_func
=
virStorageBackendGetBuildVolFromFunction
(
conn
,
vol
,
inputvol
);
if
(
!
create_func
)
return
-
1
;
}
else
if
(
vol
->
target
.
format
==
VIR_STORAGE_VOL_FILE_RAW
)
{
create_func
=
c
reateRaw
;
create_func
=
virStorageBackendC
reateRaw
;
}
else
if
(
vol
->
target
.
format
==
VIR_STORAGE_VOL_FILE_DIR
)
{
create_func
=
createFileDir
;
}
else
if
((
tool_type
=
findImageTool
(
NULL
))
!=
-
1
)
{
if
((
create_func
=
toolTypeToFunction
(
conn
,
tool_type
))
==
NULL
)
}
else
if
((
tool_type
=
virStorageBackendFindFSImageTool
(
NULL
))
!=
-
1
)
{
create_func
=
virStorageBackendFSImageToolTypeToFunc
(
conn
,
tool_type
);
if
(
!
create_func
)
return
-
1
;
}
else
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录