Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
aab2e8f7
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
aab2e8f7
编写于
9月 08, 2010
作者:
A
Anthony Liguori
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'kwolf/for-anthony' into staging
上级
dccbe6fb
7ec5e6a4
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
427 addition
and
134 deletion
+427
-134
block.c
block.c
+9
-4
block.h
block.h
+1
-1
block/nbd.c
block/nbd.c
+49
-19
block/qcow2-cluster.c
block/qcow2-cluster.c
+12
-4
block/raw-posix.c
block/raw-posix.c
+8
-5
block/sheepdog.c
block/sheepdog.c
+0
-10
block/vvfat.c
block/vvfat.c
+1
-1
hw/ide/core.c
hw/ide/core.c
+2
-2
hw/lsi53c895a.c
hw/lsi53c895a.c
+2
-2
hw/scsi-disk.c
hw/scsi-disk.c
+108
-22
hw/scsi-generic.c
hw/scsi-generic.c
+14
-4
hw/virtio-blk.c
hw/virtio-blk.c
+5
-0
hw/virtio.c
hw/virtio.c
+24
-14
hw/virtio.h
hw/virtio.h
+3
-0
nbd.c
nbd.c
+106
-12
nbd.h
nbd.h
+4
-1
posix-aio-compat.c
posix-aio-compat.c
+1
-0
qemu-doc.texi
qemu-doc.texi
+7
-0
qemu-img.c
qemu-img.c
+3
-2
qemu-io.c
qemu-io.c
+2
-5
qemu-nbd.c
qemu-nbd.c
+3
-1
savevm.c
savevm.c
+63
-25
未找到文件。
block.c
浏览文件 @
aab2e8f7
...
...
@@ -745,6 +745,7 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
int
bdrv_commit
(
BlockDriverState
*
bs
)
{
BlockDriver
*
drv
=
bs
->
drv
;
BlockDriver
*
backing_drv
;
int64_t
sector
,
total_sectors
;
int
n
,
ro
,
open_flags
;
int
ret
=
0
,
rw_ret
=
0
;
...
...
@@ -762,7 +763,8 @@ int bdrv_commit(BlockDriverState *bs)
if
(
bs
->
backing_hd
->
keep_read_only
)
{
return
-
EACCES
;
}
backing_drv
=
bs
->
backing_hd
->
drv
;
ro
=
bs
->
backing_hd
->
read_only
;
strncpy
(
filename
,
bs
->
backing_hd
->
filename
,
sizeof
(
filename
));
open_flags
=
bs
->
backing_hd
->
open_flags
;
...
...
@@ -772,12 +774,14 @@ int bdrv_commit(BlockDriverState *bs)
bdrv_delete
(
bs
->
backing_hd
);
bs
->
backing_hd
=
NULL
;
bs_rw
=
bdrv_new
(
""
);
rw_ret
=
bdrv_open
(
bs_rw
,
filename
,
open_flags
|
BDRV_O_RDWR
,
drv
);
rw_ret
=
bdrv_open
(
bs_rw
,
filename
,
open_flags
|
BDRV_O_RDWR
,
backing_drv
);
if
(
rw_ret
<
0
)
{
bdrv_delete
(
bs_rw
);
/* try to re-open read-only */
bs_ro
=
bdrv_new
(
""
);
ret
=
bdrv_open
(
bs_ro
,
filename
,
open_flags
&
~
BDRV_O_RDWR
,
drv
);
ret
=
bdrv_open
(
bs_ro
,
filename
,
open_flags
&
~
BDRV_O_RDWR
,
backing_drv
);
if
(
ret
<
0
)
{
bdrv_delete
(
bs_ro
);
/* drive not functional anymore */
...
...
@@ -828,7 +832,8 @@ ro_cleanup:
bdrv_delete
(
bs
->
backing_hd
);
bs
->
backing_hd
=
NULL
;
bs_ro
=
bdrv_new
(
""
);
ret
=
bdrv_open
(
bs_ro
,
filename
,
open_flags
&
~
BDRV_O_RDWR
,
drv
);
ret
=
bdrv_open
(
bs_ro
,
filename
,
open_flags
&
~
BDRV_O_RDWR
,
backing_drv
);
if
(
ret
<
0
)
{
bdrv_delete
(
bs_ro
);
/* drive not functional anymore */
...
...
block.h
浏览文件 @
aab2e8f7
...
...
@@ -35,7 +35,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_O_NO_BACKING 0x0100
/* don't open the backing file */
#define BDRV_O_NO_FLUSH 0x0200
/* disable flushing on this disk */
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB
| BDRV_O_NO_FLUSH
)
#define BDRV_SECTOR_BITS 9
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
...
...
block/nbd.c
浏览文件 @
aab2e8f7
...
...
@@ -33,6 +33,8 @@
#include <sys/types.h>
#include <unistd.h>
#define EN_OPTSTR ":exportname="
typedef
struct
BDRVNBDState
{
int
sock
;
off_t
size
;
...
...
@@ -42,55 +44,83 @@ typedef struct BDRVNBDState {
static
int
nbd_open
(
BlockDriverState
*
bs
,
const
char
*
filename
,
int
flags
)
{
BDRVNBDState
*
s
=
bs
->
opaque
;
uint32_t
nbdflags
;
char
*
file
;
char
*
name
;
const
char
*
host
;
const
char
*
unixpath
;
int
sock
;
off_t
size
;
size_t
blocksize
;
int
ret
;
int
err
=
-
EINVAL
;
file
=
qemu_strdup
(
filename
);
if
(
!
strstart
(
filename
,
"nbd:"
,
&
host
))
return
-
EINVAL
;
name
=
strstr
(
file
,
EN_OPTSTR
);
if
(
name
)
{
if
(
name
[
strlen
(
EN_OPTSTR
)]
==
0
)
{
goto
out
;
}
name
[
0
]
=
0
;
name
+=
strlen
(
EN_OPTSTR
);
}
if
(
!
strstart
(
file
,
"nbd:"
,
&
host
))
{
goto
out
;
}
if
(
strstart
(
host
,
"unix:"
,
&
unixpath
))
{
if
(
unixpath
[
0
]
!=
'/'
)
return
-
EINVAL
;
if
(
unixpath
[
0
]
!=
'/'
)
{
goto
out
;
}
sock
=
unix_socket_outgoing
(
unixpath
);
}
else
{
uint16_t
port
;
uint16_t
port
=
NBD_DEFAULT_PORT
;
char
*
p
,
*
r
;
char
hostname
[
128
];
pstrcpy
(
hostname
,
128
,
host
);
p
=
strchr
(
hostname
,
':'
);
if
(
p
==
NULL
)
return
-
EINVAL
;
if
(
p
!=
NULL
)
{
*
p
=
'\0'
;
p
++
;
port
=
strtol
(
p
,
&
r
,
0
);
if
(
r
==
p
)
{
goto
out
;
}
}
else
if
(
name
==
NULL
)
{
goto
out
;
}
*
p
=
'\0'
;
p
++
;
port
=
strtol
(
p
,
&
r
,
0
);
if
(
r
==
p
)
return
-
EINVAL
;
sock
=
tcp_socket_outgoing
(
hostname
,
port
);
}
if
(
sock
==
-
1
)
return
-
errno
;
if
(
sock
==
-
1
)
{
err
=
-
errno
;
goto
out
;
}
ret
=
nbd_receive_negotiate
(
sock
,
&
size
,
&
blocksize
);
if
(
ret
==
-
1
)
return
-
errno
;
ret
=
nbd_receive_negotiate
(
sock
,
name
,
&
nbdflags
,
&
size
,
&
blocksize
);
if
(
ret
==
-
1
)
{
err
=
-
errno
;
goto
out
;
}
s
->
sock
=
sock
;
s
->
size
=
size
;
s
->
blocksize
=
blocksize
;
err
=
0
;
return
0
;
out:
qemu_free
(
file
);
return
err
;
}
static
int
nbd_read
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
...
...
block/qcow2-cluster.c
浏览文件 @
aab2e8f7
...
...
@@ -655,7 +655,7 @@ static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,
int
ret
;
BLKDBG_EVENT
(
bs
->
file
,
BLKDBG_L2_UPDATE
);
ret
=
bdrv_pwrite
_sync
(
bs
->
file
,
l2_offset
+
start_offset
,
ret
=
bdrv_pwrite
(
bs
->
file
,
l2_offset
+
start_offset
,
&
l2_table
[
l2_start_index
],
len
);
if
(
ret
<
0
)
{
return
ret
;
...
...
@@ -718,9 +718,17 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
goto
err
;
}
for
(
i
=
0
;
i
<
j
;
i
++
)
qcow2_free_any_clusters
(
bs
,
be64_to_cpu
(
old_cluster
[
i
])
&
~
QCOW_OFLAG_COPIED
,
1
);
/*
* If this was a COW, we need to decrease the refcount of the old cluster.
* Also flush bs->file to get the right order for L2 and refcount update.
*/
if
(
j
!=
0
)
{
bdrv_flush
(
bs
->
file
);
for
(
i
=
0
;
i
<
j
;
i
++
)
{
qcow2_free_any_clusters
(
bs
,
be64_to_cpu
(
old_cluster
[
i
])
&
~
QCOW_OFLAG_COPIED
,
1
);
}
}
ret
=
0
;
err:
...
...
block/raw-posix.c
浏览文件 @
aab2e8f7
...
...
@@ -48,6 +48,7 @@
#endif
#ifdef __linux__
#include <sys/ioctl.h>
#include <sys/param.h>
#include <linux/cdrom.h>
#include <linux/fd.h>
#endif
...
...
@@ -868,8 +869,13 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
s
->
type
=
FTYPE_FILE
;
#if defined(__linux__)
if
(
strstart
(
filename
,
"/dev/sg"
,
NULL
))
{
bs
->
sg
=
1
;
{
char
resolved_path
[
MAXPATHLEN
],
*
temp
;
temp
=
realpath
(
filename
,
resolved_path
);
if
(
temp
&&
strstart
(
temp
,
"/dev/sg"
,
NULL
))
{
bs
->
sg
=
1
;
}
}
#endif
...
...
@@ -1154,9 +1160,6 @@ static int cdrom_probe_device(const char *filename)
int
fd
,
ret
;
int
prio
=
0
;
if
(
strstart
(
filename
,
"/dev/cd"
,
NULL
))
prio
=
50
;
fd
=
open
(
filename
,
O_RDONLY
|
O_NONBLOCK
);
if
(
fd
<
0
)
{
goto
out
;
...
...
block/sheepdog.c
浏览文件 @
aab2e8f7
...
...
@@ -8,16 +8,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _WIN32
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <netinet/tcp.h>
#define closesocket(s) close(s)
#endif
#include "qemu-common.h"
#include "qemu-error.h"
...
...
block/vvfat.c
浏览文件 @
aab2e8f7
...
...
@@ -512,7 +512,7 @@ static inline uint8_t fat_chksum(const direntry_t* entry)
for
(
i
=
0
;
i
<
11
;
i
++
)
{
unsigned
char
c
;
c
=
(
i
<
=
8
)
?
entry
->
name
[
i
]
:
entry
->
extension
[
i
-
8
];
c
=
(
i
<
8
)
?
entry
->
name
[
i
]
:
entry
->
extension
[
i
-
8
];
chksum
=
(((
chksum
&
0xfe
)
>>
1
)
|
((
chksum
&
0x01
)
?
0x80
:
0
))
+
c
;
}
...
...
hw/ide/core.c
浏览文件 @
aab2e8f7
...
...
@@ -139,6 +139,7 @@ static void ide_identify(IDEState *s)
put_le16
(
p
+
61
,
s
->
nb_sectors
>>
16
);
put_le16
(
p
+
62
,
0x07
);
/* single word dma0-2 supported */
put_le16
(
p
+
63
,
0x07
);
/* mdma0-2 supported */
put_le16
(
p
+
64
,
0x03
);
/* pio3-4 supported */
put_le16
(
p
+
65
,
120
);
put_le16
(
p
+
66
,
120
);
put_le16
(
p
+
67
,
120
);
...
...
@@ -199,13 +200,12 @@ static void ide_atapi_identify(IDEState *s)
put_le16
(
p
+
53
,
7
);
/* words 64-70, 54-58, 88 valid */
put_le16
(
p
+
62
,
7
);
/* single word dma0-2 supported */
put_le16
(
p
+
63
,
7
);
/* mdma0-2 supported */
put_le16
(
p
+
64
,
0x3f
);
/* PIO modes supported */
#else
put_le16
(
p
+
49
,
1
<<
9
);
/* LBA supported, no DMA */
put_le16
(
p
+
53
,
3
);
/* words 64-70, 54-58 valid */
put_le16
(
p
+
63
,
0x103
);
/* DMA modes XXX: may be incorrect */
put_le16
(
p
+
64
,
1
);
/* PIO modes */
#endif
put_le16
(
p
+
64
,
3
);
/* pio3-4 supported */
put_le16
(
p
+
65
,
0xb4
);
/* minimum DMA multiword tx cycle time */
put_le16
(
p
+
66
,
0xb4
);
/* recommended DMA multiword tx cycle time */
put_le16
(
p
+
67
,
0x12c
);
/* minimum PIO cycle time without flow control */
...
...
hw/lsi53c895a.c
浏览文件 @
aab2e8f7
...
...
@@ -600,7 +600,7 @@ static void lsi_queue_command(LSIState *s)
{
lsi_request
*
p
=
s
->
current
;
DPRINTF
(
"Queueing tag=0x%x
\n
"
,
s
->
current_
tag
);
DPRINTF
(
"Queueing tag=0x%x
\n
"
,
p
->
tag
);
assert
(
s
->
current
!=
NULL
);
assert
(
s
->
current
->
dma_len
==
0
);
QTAILQ_INSERT_TAIL
(
&
s
->
queue
,
s
->
current
,
next
);
...
...
@@ -880,7 +880,7 @@ static void lsi_do_msgout(LSIState *s)
break
;
case
0x20
:
/* SIMPLE queue */
s
->
select_tag
|=
lsi_get_msgbyte
(
s
)
|
LSI_TAG_VALID
;
DPRINTF
(
"SIMPLE queue tag=0x%x
\n
"
,
s
->
curren
t_tag
&
0xff
);
DPRINTF
(
"SIMPLE queue tag=0x%x
\n
"
,
s
->
selec
t_tag
&
0xff
);
break
;
case
0x21
:
/* HEAD of queue */
BADF
(
"HEAD queue not implemented
\n
"
);
...
...
hw/scsi-disk.c
浏览文件 @
aab2e8f7
...
...
@@ -135,7 +135,7 @@ static void scsi_read_complete(void * opaque, int ret)
scsi_command_complete
(
r
,
CHECK_CONDITION
,
NO_SENSE
);
return
;
}
DPRINTF
(
"Data ready tag=0x%x len=%
"
PRId64
"
\n
"
,
r
->
req
.
tag
,
r
->
iov
.
iov_len
);
DPRINTF
(
"Data ready tag=0x%x len=%
zd
\n
"
,
r
->
req
.
tag
,
r
->
iov
.
iov_len
);
r
->
req
.
bus
->
complete
(
r
->
req
.
bus
,
SCSI_REASON_DATA
,
r
->
req
.
tag
,
r
->
iov
.
iov_len
);
}
...
...
@@ -155,7 +155,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return
;
}
if
(
r
->
sector_count
==
(
uint32_t
)
-
1
)
{
DPRINTF
(
"Read buf_len=%
"
PRId64
"
\n
"
,
r
->
iov
.
iov_len
);
DPRINTF
(
"Read buf_len=%
zd
\n
"
,
r
->
iov
.
iov_len
);
r
->
sector_count
=
0
;
r
->
req
.
bus
->
complete
(
r
->
req
.
bus
,
SCSI_REASON_DATA
,
r
->
req
.
tag
,
r
->
iov
.
iov_len
);
return
;
...
...
@@ -486,16 +486,26 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
return
buflen
;
}
static
int
mode_sense_page
(
SCSIRequest
*
req
,
int
page
,
uint8_t
*
p
)
static
int
mode_sense_page
(
SCSIRequest
*
req
,
int
page
,
uint8_t
*
p
,
int
page_control
)
{
SCSIDiskState
*
s
=
DO_UPCAST
(
SCSIDiskState
,
qdev
,
req
->
dev
);
BlockDriverState
*
bdrv
=
s
->
bs
;
int
cylinders
,
heads
,
secs
;
/*
* If Changeable Values are requested, a mask denoting those mode parameters
* that are changeable shall be returned. As we currently don't support
* parameter changes via MODE_SELECT all bits are returned set to zero.
* The buffer was already menset to zero by the caller of this function.
*/
switch
(
page
)
{
case
4
:
/* Rigid disk device geometry page. */
p
[
0
]
=
4
;
p
[
1
]
=
0x16
;
if
(
page_control
==
1
)
{
/* Changeable Values */
return
p
[
1
]
+
2
;
}
/* if a geometry hint is available, use it */
bdrv_get_geometry_hint
(
bdrv
,
&
cylinders
,
&
heads
,
&
secs
);
p
[
2
]
=
(
cylinders
>>
16
)
&
0xff
;
...
...
@@ -520,11 +530,14 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
/* Medium rotation rate [rpm], 5400 rpm */
p
[
20
]
=
(
5400
>>
8
)
&
0xff
;
p
[
21
]
=
5400
&
0xff
;
return
0x16
;
return
p
[
1
]
+
2
;
case
5
:
/* Flexible disk device geometry page. */
p
[
0
]
=
5
;
p
[
1
]
=
0x1e
;
if
(
page_control
==
1
)
{
/* Changeable Values */
return
p
[
1
]
+
2
;
}
/* Transfer rate [kbit/s], 5Mbit/s */
p
[
2
]
=
5000
>>
8
;
p
[
3
]
=
5000
&
0xff
;
...
...
@@ -556,21 +569,27 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
/* Medium rotation rate [rpm], 5400 rpm */
p
[
28
]
=
(
5400
>>
8
)
&
0xff
;
p
[
29
]
=
5400
&
0xff
;
return
0x1e
;
return
p
[
1
]
+
2
;
case
8
:
/* Caching page. */
p
[
0
]
=
8
;
p
[
1
]
=
0x12
;
if
(
page_control
==
1
)
{
/* Changeable Values */
return
p
[
1
]
+
2
;
}
if
(
bdrv_enable_write_cache
(
s
->
bs
))
{
p
[
2
]
=
4
;
/* WCE */
}
return
20
;
return
p
[
1
]
+
2
;
case
0x2a
:
/* CD Capabilities and Mechanical Status page. */
if
(
bdrv_get_type_hint
(
bdrv
)
!=
BDRV_TYPE_CDROM
)
return
0
;
p
[
0
]
=
0x2a
;
p
[
1
]
=
0x14
;
if
(
page_control
==
1
)
{
/* Changeable Values */
return
p
[
1
]
+
2
;
}
p
[
2
]
=
3
;
// CD-R & CD-RW read
p
[
3
]
=
0
;
// Writing not supported
p
[
4
]
=
0x7f
;
/* Audio, composite, digital out,
...
...
@@ -594,7 +613,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
p
[
19
]
=
(
16
*
176
)
&
0xff
;
p
[
20
]
=
(
16
*
176
)
>>
8
;
// 16x write speed current
p
[
21
]
=
(
16
*
176
)
&
0xff
;
return
2
2
;
return
p
[
1
]
+
2
;
default:
return
0
;
...
...
@@ -605,29 +624,46 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
{
SCSIDiskState
*
s
=
DO_UPCAST
(
SCSIDiskState
,
qdev
,
req
->
dev
);
uint64_t
nb_sectors
;
int
page
,
dbd
,
buflen
;
int
page
,
dbd
,
buflen
,
page_control
;
uint8_t
*
p
;
uint8_t
dev_specific_param
;
dbd
=
req
->
cmd
.
buf
[
1
]
&
0x8
;
page
=
req
->
cmd
.
buf
[
2
]
&
0x3f
;
DPRINTF
(
"Mode Sense (page %d, len %zd)
\n
"
,
page
,
req
->
cmd
.
xfer
);
page_control
=
(
req
->
cmd
.
buf
[
2
]
&
0xc0
)
>>
6
;
DPRINTF
(
"Mode Sense(%d) (page %d, xfer %zd, page_control %d)
\n
"
,
(
req
->
cmd
.
buf
[
0
]
==
MODE_SENSE
)
?
6
:
10
,
page
,
req
->
cmd
.
xfer
,
page_control
);
memset
(
outbuf
,
0
,
req
->
cmd
.
xfer
);
p
=
outbuf
;
p
[
1
]
=
0
;
/* Default media type. */
p
[
3
]
=
0
;
/* Block descriptor length. */
if
(
bdrv_is_read_only
(
s
->
bs
))
{
p
[
2
]
=
0x80
;
/* Readonly. */
dev_specific_param
=
0x80
;
/* Readonly. */
}
else
{
dev_specific_param
=
0x00
;
}
if
(
req
->
cmd
.
buf
[
0
]
==
MODE_SENSE
)
{
p
[
1
]
=
0
;
/* Default media type. */
p
[
2
]
=
dev_specific_param
;
p
[
3
]
=
0
;
/* Block descriptor length. */
p
+=
4
;
}
else
{
/* MODE_SENSE_10 */
p
[
2
]
=
0
;
/* Default media type. */
p
[
3
]
=
dev_specific_param
;
p
[
6
]
=
p
[
7
]
=
0
;
/* Block descriptor length. */
p
+=
8
;
}
p
+=
4
;
bdrv_get_geometry
(
s
->
bs
,
&
nb_sectors
);
if
((
~
dbd
)
&
nb_sectors
)
{
outbuf
[
3
]
=
8
;
/* Block descriptor length */
if
(
!
dbd
&&
nb_sectors
)
{
if
(
req
->
cmd
.
buf
[
0
]
==
MODE_SENSE
)
{
outbuf
[
3
]
=
8
;
/* Block descriptor length */
}
else
{
/* MODE_SENSE_10 */
outbuf
[
7
]
=
8
;
/* Block descriptor length */
}
nb_sectors
/=
s
->
cluster_size
;
nb_sectors
--
;
if
(
nb_sectors
>
0xffffff
)
nb_sectors
=
0
xffffff
;
nb_sectors
=
0
;
p
[
0
]
=
0
;
/* media density code */
p
[
1
]
=
(
nb_sectors
>>
16
)
&
0xff
;
p
[
2
]
=
(
nb_sectors
>>
8
)
&
0xff
;
...
...
@@ -639,21 +675,37 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
p
+=
8
;
}
if
(
page_control
==
3
)
{
/* Saved Values */
return
-
1
;
/* ILLEGAL_REQUEST */
}
switch
(
page
)
{
case
0x04
:
case
0x05
:
case
0x08
:
case
0x2a
:
p
+=
mode_sense_page
(
req
,
page
,
p
);
p
+=
mode_sense_page
(
req
,
page
,
p
,
page_control
);
break
;
case
0x3f
:
p
+=
mode_sense_page
(
req
,
0x08
,
p
);
p
+=
mode_sense_page
(
req
,
0x2a
,
p
);
p
+=
mode_sense_page
(
req
,
0x08
,
p
,
page_control
);
p
+=
mode_sense_page
(
req
,
0x2a
,
p
,
page_control
);
break
;
default:
return
-
1
;
/* ILLEGAL_REQUEST */
}
buflen
=
p
-
outbuf
;
outbuf
[
0
]
=
buflen
-
4
;
/*
* The mode data length field specifies the length in bytes of the
* following data that is available to be transferred. The mode data
* length does not include itself.
*/
if
(
req
->
cmd
.
buf
[
0
]
==
MODE_SENSE
)
{
outbuf
[
0
]
=
buflen
-
1
;
}
else
{
/* MODE_SENSE_10 */
outbuf
[
0
]
=
((
buflen
-
2
)
>>
8
)
&
0xff
;
outbuf
[
1
]
=
(
buflen
-
2
)
&
0xff
;
}
if
(
buflen
>
req
->
cmd
.
xfer
)
buflen
=
req
->
cmd
.
xfer
;
return
buflen
;
...
...
@@ -840,6 +892,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
break
;
case
VERIFY
:
break
;
case
REZERO_UNIT
:
DPRINTF
(
"Rezero Unit
\n
"
);
if
(
!
bdrv_is_inserted
(
s
->
bs
))
{
goto
not_ready
;
}
break
;
default:
goto
illegal_request
;
}
...
...
@@ -959,6 +1017,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case
SERVICE_ACTION_IN
:
case
REPORT_LUNS
:
case
VERIFY
:
case
REZERO_UNIT
:
rc
=
scsi_disk_emulate_command
(
&
r
->
req
,
outbuf
);
if
(
rc
>
0
)
{
r
->
iov
.
iov_len
=
rc
;
...
...
@@ -982,13 +1041,40 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case
WRITE_10
:
case
WRITE_12
:
case
WRITE_16
:
DPRINTF
(
"Write (sector %"
PRId64
", count %d)
\n
"
,
lba
,
len
);
case
WRITE_VERIFY
:
case
WRITE_VERIFY_12
:
case
WRITE_VERIFY_16
:
DPRINTF
(
"Write %s(sector %"
PRId64
", count %d)
\n
"
,
(
command
&
0xe
)
==
0xe
?
"And Verify "
:
""
,
lba
,
len
);
if
(
lba
>
s
->
max_lba
)
goto
illegal_lba
;
r
->
sector
=
lba
*
s
->
cluster_size
;
r
->
sector_count
=
len
*
s
->
cluster_size
;
is_write
=
1
;
break
;
case
MODE_SELECT
:
DPRINTF
(
"Mode Select(6) (len %d)
\n
"
,
len
);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if
(
len
>
12
)
{
goto
fail
;
}
break
;
case
MODE_SELECT_10
:
DPRINTF
(
"Mode Select(10) (len %d)
\n
"
,
len
);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
if
(
len
>
16
)
{
goto
fail
;
}
break
;
case
SEEK_6
:
case
SEEK_10
:
DPRINTF
(
"Seek(%d) (sector %"
PRId64
")
\n
"
,
command
==
SEEK_6
?
6
:
10
,
lba
);
if
(
lba
>
s
->
max_lba
)
{
goto
illegal_lba
;
}
break
;
default:
DPRINTF
(
"Unknown SCSI command (%2.2x)
\n
"
,
buf
[
0
]);
fail:
...
...
hw/scsi-generic.c
浏览文件 @
aab2e8f7
...
...
@@ -164,7 +164,7 @@ static void scsi_read_complete(void * opaque, int ret)
int
len
;
if
(
ret
)
{
DPRINTF
(
"IO error
\n
"
);
DPRINTF
(
"IO error
ret %d
\n
"
,
ret
);
scsi_command_complete
(
r
,
ret
);
return
;
}
...
...
@@ -236,7 +236,7 @@ static void scsi_write_complete(void * opaque, int ret)
if
(
r
->
req
.
cmd
.
buf
[
0
]
==
MODE_SELECT
&&
r
->
req
.
cmd
.
buf
[
4
]
==
12
&&
s
->
qdev
.
type
==
TYPE_TAPE
)
{
s
->
qdev
.
blocksize
=
(
r
->
buf
[
9
]
<<
16
)
|
(
r
->
buf
[
10
]
<<
8
)
|
r
->
buf
[
11
];
DPRINTF
(
"block size %d
\n
"
,
s
->
blocksize
);
DPRINTF
(
"block size %d
\n
"
,
s
->
qdev
.
blocksize
);
}
scsi_command_complete
(
r
,
ret
);
...
...
@@ -351,8 +351,18 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
}
scsi_req_fixup
(
&
r
->
req
);
DPRINTF
(
"Command: lun=%d tag=0x%x data=0x%02x len %d
\n
"
,
lun
,
tag
,
cmd
[
0
],
r
->
req
.
cmd
.
xfer
);
DPRINTF
(
"Command: lun=%d tag=0x%x len %zd data=0x%02x"
,
lun
,
tag
,
r
->
req
.
cmd
.
xfer
,
cmd
[
0
]);
#ifdef DEBUG_SCSI
{
int
i
;
for
(
i
=
1
;
i
<
r
->
req
.
cmd
.
len
;
i
++
)
{
printf
(
" 0x%02x"
,
cmd
[
i
]);
}
printf
(
"
\n
"
);
}
#endif
if
(
r
->
req
.
cmd
.
xfer
==
0
)
{
if
(
r
->
buf
!=
NULL
)
...
...
hw/virtio-blk.c
浏览文件 @
aab2e8f7
...
...
@@ -481,6 +481,11 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_buffer
(
f
,
(
unsigned
char
*
)
&
req
->
elem
,
sizeof
(
req
->
elem
));
req
->
next
=
s
->
rq
;
s
->
rq
=
req
;
virtqueue_map_sg
(
req
->
elem
.
in_sg
,
req
->
elem
.
in_addr
,
req
->
elem
.
in_num
,
1
);
virtqueue_map_sg
(
req
->
elem
.
out_sg
,
req
->
elem
.
out_addr
,
req
->
elem
.
out_num
,
0
);
}
return
0
;
...
...
hw/virtio.c
浏览文件 @
aab2e8f7
...
...
@@ -360,11 +360,26 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
return
0
;
}
void
virtqueue_map_sg
(
struct
iovec
*
sg
,
target_phys_addr_t
*
addr
,
size_t
num_sg
,
int
is_write
)
{
unsigned
int
i
;
target_phys_addr_t
len
;
for
(
i
=
0
;
i
<
num_sg
;
i
++
)
{
len
=
sg
[
i
].
iov_len
;
sg
[
i
].
iov_base
=
cpu_physical_memory_map
(
addr
[
i
],
&
len
,
is_write
);
if
(
sg
[
i
].
iov_base
==
NULL
||
len
!=
sg
[
i
].
iov_len
)
{
fprintf
(
stderr
,
"virtio: trying to map MMIO memory
\n
"
);
exit
(
1
);
}
}
}
int
virtqueue_pop
(
VirtQueue
*
vq
,
VirtQueueElement
*
elem
)
{
unsigned
int
i
,
head
,
max
;
target_phys_addr_t
desc_pa
=
vq
->
vring
.
desc
;
target_phys_addr_t
len
;
if
(
!
virtqueue_num_heads
(
vq
,
vq
->
last_avail_idx
))
return
0
;
...
...
@@ -388,28 +403,19 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
i
=
0
;
}
/* Collect all the descriptors */
do
{
struct
iovec
*
sg
;
int
is_write
=
0
;
if
(
vring_desc_flags
(
desc_pa
,
i
)
&
VRING_DESC_F_WRITE
)
{
elem
->
in_addr
[
elem
->
in_num
]
=
vring_desc_addr
(
desc_pa
,
i
);
sg
=
&
elem
->
in_sg
[
elem
->
in_num
++
];
is_write
=
1
;
}
else
}
else
{
elem
->
out_addr
[
elem
->
out_num
]
=
vring_desc_addr
(
desc_pa
,
i
);
sg
=
&
elem
->
out_sg
[
elem
->
out_num
++
];
}
/* Grab the first descriptor, and check it's OK. */
sg
->
iov_len
=
vring_desc_len
(
desc_pa
,
i
);
len
=
sg
->
iov_len
;
sg
->
iov_base
=
cpu_physical_memory_map
(
vring_desc_addr
(
desc_pa
,
i
),
&
len
,
is_write
);
if
(
sg
->
iov_base
==
NULL
||
len
!=
sg
->
iov_len
)
{
fprintf
(
stderr
,
"virtio: trying to map MMIO memory
\n
"
);
exit
(
1
);
}
/* If we've got too many, that implies a descriptor loop. */
if
((
elem
->
in_num
+
elem
->
out_num
)
>
max
)
{
...
...
@@ -418,6 +424,10 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
}
}
while
((
i
=
virtqueue_next_desc
(
desc_pa
,
i
,
max
))
!=
max
);
/* Now map what we have collected */
virtqueue_map_sg
(
elem
->
in_sg
,
elem
->
in_addr
,
elem
->
in_num
,
1
);
virtqueue_map_sg
(
elem
->
out_sg
,
elem
->
out_addr
,
elem
->
out_num
,
0
);
elem
->
index
=
head
;
vq
->
inuse
++
;
...
...
hw/virtio.h
浏览文件 @
aab2e8f7
...
...
@@ -81,6 +81,7 @@ typedef struct VirtQueueElement
unsigned
int
out_num
;
unsigned
int
in_num
;
target_phys_addr_t
in_addr
[
VIRTQUEUE_MAX_SIZE
];
target_phys_addr_t
out_addr
[
VIRTQUEUE_MAX_SIZE
];
struct
iovec
in_sg
[
VIRTQUEUE_MAX_SIZE
];
struct
iovec
out_sg
[
VIRTQUEUE_MAX_SIZE
];
}
VirtQueueElement
;
...
...
@@ -142,6 +143,8 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count);
void
virtqueue_fill
(
VirtQueue
*
vq
,
const
VirtQueueElement
*
elem
,
unsigned
int
len
,
unsigned
int
idx
);
void
virtqueue_map_sg
(
struct
iovec
*
sg
,
target_phys_addr_t
*
addr
,
size_t
num_sg
,
int
is_write
);
int
virtqueue_pop
(
VirtQueue
*
vq
,
VirtQueueElement
*
elem
);
int
virtqueue_avail_bytes
(
VirtQueue
*
vq
,
int
in_bytes
,
int
out_bytes
);
...
...
nbd.c
浏览文件 @
aab2e8f7
...
...
@@ -62,6 +62,8 @@
#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
#define NBD_DISCONNECT _IO(0xab, 8)
#define NBD_OPT_EXPORT_NAME (1 << 0)
/* That's all folks */
#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
...
...
@@ -296,22 +298,27 @@ int nbd_negotiate(int csock, off_t size)
return
0
;
}
int
nbd_receive_negotiate
(
int
csock
,
off_t
*
size
,
size_t
*
blocksize
)
int
nbd_receive_negotiate
(
int
csock
,
const
char
*
name
,
uint32_t
*
flags
,
off_t
*
size
,
size_t
*
blocksize
)
{
char
buf
[
8
+
8
+
8
+
128
];
uint64_t
magic
;
char
buf
[
256
];
uint64_t
magic
,
s
;
uint16_t
tmp
;
TRACE
(
"Receiving negotation."
);
if
(
read_sync
(
csock
,
buf
,
sizeof
(
buf
))
!=
sizeof
(
buf
)
)
{
if
(
read_sync
(
csock
,
buf
,
8
)
!=
8
)
{
LOG
(
"read failed"
);
errno
=
EINVAL
;
return
-
1
;
}
magic
=
be64_to_cpup
((
uint64_t
*
)(
buf
+
8
));
*
size
=
be64_to_cpup
((
uint64_t
*
)(
buf
+
16
));
*
blocksize
=
1024
;
buf
[
8
]
=
'\0'
;
if
(
strlen
(
buf
)
==
0
)
{
LOG
(
"server connection closed"
);
errno
=
EINVAL
;
return
-
1
;
}
TRACE
(
"Magic is %c%c%c%c%c%c%c%c"
,
qemu_isprint
(
buf
[
0
])
?
buf
[
0
]
:
'.'
,
...
...
@@ -322,8 +329,6 @@ int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize)
qemu_isprint
(
buf
[
5
])
?
buf
[
5
]
:
'.'
,
qemu_isprint
(
buf
[
6
])
?
buf
[
6
]
:
'.'
,
qemu_isprint
(
buf
[
7
])
?
buf
[
7
]
:
'.'
);
TRACE
(
"Magic is 0x%"
PRIx64
,
magic
);
TRACE
(
"Size is %"
PRIu64
,
*
size
);
if
(
memcmp
(
buf
,
"NBDMAGIC"
,
8
)
!=
0
)
{
LOG
(
"Invalid magic received"
);
...
...
@@ -331,10 +336,99 @@ int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize)
return
-
1
;
}
TRACE
(
"Checking magic"
);
if
(
read_sync
(
csock
,
&
magic
,
sizeof
(
magic
))
!=
sizeof
(
magic
))
{
LOG
(
"read failed"
);
errno
=
EINVAL
;
return
-
1
;
}
magic
=
be64_to_cpu
(
magic
);
TRACE
(
"Magic is 0x%"
PRIx64
,
magic
);
if
(
name
)
{
uint32_t
reserved
=
0
;
uint32_t
opt
;
uint32_t
namesize
;
TRACE
(
"Checking magic (opts_magic)"
);
if
(
magic
!=
0x49484156454F5054LL
)
{
LOG
(
"Bad magic received"
);
errno
=
EINVAL
;
return
-
1
;
}
if
(
read_sync
(
csock
,
&
tmp
,
sizeof
(
tmp
))
!=
sizeof
(
tmp
))
{
LOG
(
"flags read failed"
);
errno
=
EINVAL
;
return
-
1
;
}
*
flags
=
be16_to_cpu
(
tmp
)
<<
16
;
/* reserved for future use */
if
(
write_sync
(
csock
,
&
reserved
,
sizeof
(
reserved
))
!=
sizeof
(
reserved
))
{
LOG
(
"write failed (reserved)"
);
errno
=
EINVAL
;
return
-
1
;
}
/* write the export name */
magic
=
cpu_to_be64
(
magic
);
if
(
write_sync
(
csock
,
&
magic
,
sizeof
(
magic
))
!=
sizeof
(
magic
))
{
LOG
(
"write failed (magic)"
);
errno
=
EINVAL
;
return
-
1
;
}
opt
=
cpu_to_be32
(
NBD_OPT_EXPORT_NAME
);
if
(
write_sync
(
csock
,
&
opt
,
sizeof
(
opt
))
!=
sizeof
(
opt
))
{
LOG
(
"write failed (opt)"
);
errno
=
EINVAL
;
return
-
1
;
}
namesize
=
cpu_to_be32
(
strlen
(
name
));
if
(
write_sync
(
csock
,
&
namesize
,
sizeof
(
namesize
))
!=
sizeof
(
namesize
))
{
LOG
(
"write failed (namesize)"
);
errno
=
EINVAL
;
return
-
1
;
}
if
(
write_sync
(
csock
,
(
char
*
)
name
,
strlen
(
name
))
!=
strlen
(
name
))
{
LOG
(
"write failed (name)"
);
errno
=
EINVAL
;
return
-
1
;
}
}
else
{
TRACE
(
"Checking magic (cli_magic)"
);
if
(
magic
!=
0x00420281861253LL
)
{
LOG
(
"Bad magic received"
);
errno
=
EINVAL
;
return
-
1
;
}
}
if
(
read_sync
(
csock
,
&
s
,
sizeof
(
s
))
!=
sizeof
(
s
))
{
LOG
(
"read failed"
);
errno
=
EINVAL
;
return
-
1
;
}
*
size
=
be64_to_cpu
(
s
);
*
blocksize
=
1024
;
TRACE
(
"Size is %"
PRIu64
,
*
size
);
if
(
magic
!=
0x00420281861253LL
)
{
LOG
(
"Bad magic received"
);
if
(
!
name
)
{
if
(
read_sync
(
csock
,
flags
,
sizeof
(
*
flags
))
!=
sizeof
(
*
flags
))
{
LOG
(
"read failed (flags)"
);
errno
=
EINVAL
;
return
-
1
;
}
*
flags
=
be32_to_cpup
(
flags
);
}
else
{
if
(
read_sync
(
csock
,
&
tmp
,
sizeof
(
tmp
))
!=
sizeof
(
tmp
))
{
LOG
(
"read failed (tmp)"
);
errno
=
EINVAL
;
return
-
1
;
}
*
flags
|=
be32_to_cpu
(
tmp
);
}
if
(
read_sync
(
csock
,
&
buf
,
124
)
!=
124
)
{
LOG
(
"read failed (buf)"
);
errno
=
EINVAL
;
return
-
1
;
}
...
...
nbd.h
浏览文件 @
aab2e8f7
...
...
@@ -42,6 +42,8 @@ enum {
NBD_CMD_DISC
=
2
};
#define NBD_DEFAULT_PORT 10809
size_t
nbd_wr_sync
(
int
fd
,
void
*
buffer
,
size_t
size
,
bool
do_read
);
int
tcp_socket_outgoing
(
const
char
*
address
,
uint16_t
port
);
int
tcp_socket_incoming
(
const
char
*
address
,
uint16_t
port
);
...
...
@@ -49,7 +51,8 @@ int unix_socket_outgoing(const char *path);
int
unix_socket_incoming
(
const
char
*
path
);
int
nbd_negotiate
(
int
csock
,
off_t
size
);
int
nbd_receive_negotiate
(
int
csock
,
off_t
*
size
,
size_t
*
blocksize
);
int
nbd_receive_negotiate
(
int
csock
,
const
char
*
name
,
uint32_t
*
flags
,
off_t
*
size
,
size_t
*
blocksize
);
int
nbd_init
(
int
fd
,
int
csock
,
off_t
size
,
size_t
blocksize
);
int
nbd_send_request
(
int
csock
,
struct
nbd_request
*
request
);
int
nbd_receive_reply
(
int
csock
,
struct
nbd_reply
*
reply
);
...
...
posix-aio-compat.c
浏览文件 @
aab2e8f7
...
...
@@ -599,6 +599,7 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
acb
->
aio_type
=
QEMU_AIO_IOCTL
;
acb
->
aio_fildes
=
fd
;
acb
->
ev_signo
=
SIGUSR2
;
acb
->
async_context_id
=
get_async_context_id
();
acb
->
aio_offset
=
0
;
acb
->
aio_ioctl_buf
=
buf
;
acb
->
aio_ioctl_cmd
=
req
;
...
...
qemu-doc.texi
浏览文件 @
aab2e8f7
...
...
@@ -620,6 +620,13 @@ qemu linux1.img -hdb nbd:unix:/tmp/my_socket
qemu linux
2
.img
-
hdb nbd:unix:
/
tmp
/
my
_
socket
@end example
If the nbd
-
server uses named exports
(
since NBD
2
.
9
.
18
)
, you must use the
"exportname" option:
@example
qemu
-
cdrom nbd:localhost:exportname
=
debian
-
500
-
ppc
-
netinst
qemu
-
cdrom nbd:localhost:exportname
=
openSUSE
-
11
.
1
-
ppc
-
netinst
@end example
@node pcsys
_
network
@section Network emulation
...
...
qemu-img.c
浏览文件 @
aab2e8f7
...
...
@@ -783,7 +783,8 @@ static int img_convert(int argc, char **argv)
goto
out
;
}
out_bs
=
bdrv_new_open
(
out_filename
,
out_fmt
,
BDRV_O_FLAGS
|
BDRV_O_RDWR
);
out_bs
=
bdrv_new_open
(
out_filename
,
out_fmt
,
BDRV_O_FLAGS
|
BDRV_O_RDWR
|
BDRV_O_NO_FLUSH
);
if
(
!
out_bs
)
{
ret
=
-
1
;
goto
out
;
...
...
@@ -1286,7 +1287,7 @@ static int img_rebase(int argc, char **argv)
}
bs_new_backing
=
bdrv_new
(
"new_backing"
);
ret
=
bdrv_open
(
bs_new_backing
,
out_baseimg
,
BDRV_O_FLAGS
|
BDRV_O_RDWR
,
ret
=
bdrv_open
(
bs_new_backing
,
out_baseimg
,
BDRV_O_FLAGS
,
new_backing_drv
);
if
(
ret
)
{
error
(
"Could not open new backing file '%s'"
,
out_baseimg
);
...
...
qemu-io.c
浏览文件 @
aab2e8f7
...
...
@@ -1427,11 +1427,8 @@ alloc_f(int argc, char **argv)
cvtstr
(
offset
,
s1
,
sizeof
(
s1
));
if
(
nb_sectors
==
1
)
printf
(
"sector allocated at offset %s
\n
"
,
s1
);
else
printf
(
"%d/%d sectors allocated at offset %s
\n
"
,
sum_alloc
,
nb_sectors
,
s1
);
printf
(
"%d/%d sectors allocated at offset %s
\n
"
,
sum_alloc
,
nb_sectors
,
s1
);
return
0
;
}
...
...
qemu-nbd.c
浏览文件 @
aab2e8f7
...
...
@@ -230,6 +230,7 @@ int main(int argc, char **argv)
int
nb_fds
=
0
;
int
max_fd
;
int
persistent
=
0
;
uint32_t
nbdflags
;
while
((
ch
=
getopt_long
(
argc
,
argv
,
sopt
,
lopt
,
&
opt_ind
))
!=
-
1
)
{
switch
(
ch
)
{
...
...
@@ -398,7 +399,8 @@ int main(int argc, char **argv)
goto
out
;
}
ret
=
nbd_receive_negotiate
(
sock
,
&
size
,
&
blocksize
);
ret
=
nbd_receive_negotiate
(
sock
,
NULL
,
&
nbdflags
,
&
size
,
&
blocksize
);
if
(
ret
==
-
1
)
{
ret
=
1
;
goto
out
;
...
...
savevm.c
浏览文件 @
aab2e8f7
...
...
@@ -1837,8 +1837,10 @@ void do_savevm(Monitor *mon, const QDict *qdict)
uint32_t
vm_state_size
;
#ifdef _WIN32
struct
_timeb
tb
;
struct
tm
*
ptm
;
#else
struct
timeval
tv
;
struct
tm
tm
;
#endif
const
char
*
name
=
qdict_get_try_str
(
qdict
,
"name"
);
...
...
@@ -1869,15 +1871,6 @@ void do_savevm(Monitor *mon, const QDict *qdict)
vm_stop
(
0
);
memset
(
sn
,
0
,
sizeof
(
*
sn
));
if
(
name
)
{
ret
=
bdrv_snapshot_find
(
bs
,
old_sn
,
name
);
if
(
ret
>=
0
)
{
pstrcpy
(
sn
->
name
,
sizeof
(
sn
->
name
),
old_sn
->
name
);
pstrcpy
(
sn
->
id_str
,
sizeof
(
sn
->
id_str
),
old_sn
->
id_str
);
}
else
{
pstrcpy
(
sn
->
name
,
sizeof
(
sn
->
name
),
name
);
}
}
/* fill auxiliary fields */
#ifdef _WIN32
...
...
@@ -1891,6 +1884,24 @@ void do_savevm(Monitor *mon, const QDict *qdict)
#endif
sn
->
vm_clock_nsec
=
qemu_get_clock
(
vm_clock
);
if
(
name
)
{
ret
=
bdrv_snapshot_find
(
bs
,
old_sn
,
name
);
if
(
ret
>=
0
)
{
pstrcpy
(
sn
->
name
,
sizeof
(
sn
->
name
),
old_sn
->
name
);
pstrcpy
(
sn
->
id_str
,
sizeof
(
sn
->
id_str
),
old_sn
->
id_str
);
}
else
{
pstrcpy
(
sn
->
name
,
sizeof
(
sn
->
name
),
name
);
}
}
else
{
#ifdef _WIN32
ptm
=
localtime
(
&
tb
.
time
);
strftime
(
sn
->
name
,
sizeof
(
sn
->
name
),
"vm-%Y%m%d%H%M%S"
,
ptm
);
#else
localtime_r
(
&
tv
.
tv_sec
,
&
tm
);
strftime
(
sn
->
name
,
sizeof
(
sn
->
name
),
"vm-%Y%m%d%H%M%S"
,
&
tm
);
#endif
}
/* Delete old snapshots of the same name */
if
(
name
&&
del_existing_snapshots
(
mon
,
name
)
<
0
)
{
goto
the_end
;
...
...
@@ -2039,8 +2050,10 @@ void do_delvm(Monitor *mon, const QDict *qdict)
void
do_info_snapshots
(
Monitor
*
mon
)
{
BlockDriverState
*
bs
,
*
bs1
;
QEMUSnapshotInfo
*
sn_tab
,
*
sn
;
int
nb_sns
,
i
;
QEMUSnapshotInfo
*
sn_tab
,
*
sn
,
s
,
*
sn_info
=
&
s
;
int
nb_sns
,
i
,
ret
,
available
;
int
total
;
int
*
available_snapshots
;
char
buf
[
256
];
bs
=
bdrv_snapshots
();
...
...
@@ -2048,27 +2061,52 @@ void do_info_snapshots(Monitor *mon)
monitor_printf
(
mon
,
"No available block device supports snapshots
\n
"
);
return
;
}
monitor_printf
(
mon
,
"Snapshot devices:"
);
bs1
=
NULL
;
while
((
bs1
=
bdrv_next
(
bs1
)))
{
if
(
bdrv_can_snapshot
(
bs1
))
{
if
(
bs
==
bs1
)
monitor_printf
(
mon
,
" %s"
,
bdrv_get_device_name
(
bs1
));
}
}
monitor_printf
(
mon
,
"
\n
"
);
nb_sns
=
bdrv_snapshot_list
(
bs
,
&
sn_tab
);
if
(
nb_sns
<
0
)
{
monitor_printf
(
mon
,
"bdrv_snapshot_list: error %d
\n
"
,
nb_sns
);
return
;
}
monitor_printf
(
mon
,
"Snapshot list (from %s):
\n
"
,
bdrv_get_device_name
(
bs
));
monitor_printf
(
mon
,
"%s
\n
"
,
bdrv_snapshot_dump
(
buf
,
sizeof
(
buf
),
NULL
));
for
(
i
=
0
;
i
<
nb_sns
;
i
++
)
{
if
(
nb_sns
==
0
)
{
monitor_printf
(
mon
,
"There is no snapshot available.
\n
"
);
return
;
}
available_snapshots
=
qemu_mallocz
(
sizeof
(
int
)
*
nb_sns
);
total
=
0
;
for
(
i
=
0
;
i
<
nb_sns
;
i
++
)
{
sn
=
&
sn_tab
[
i
];
monitor_printf
(
mon
,
"%s
\n
"
,
bdrv_snapshot_dump
(
buf
,
sizeof
(
buf
),
sn
));
available
=
1
;
bs1
=
NULL
;
while
((
bs1
=
bdrv_next
(
bs1
)))
{
if
(
bdrv_can_snapshot
(
bs1
)
&&
bs1
!=
bs
)
{
ret
=
bdrv_snapshot_find
(
bs1
,
sn_info
,
sn
->
id_str
);
if
(
ret
<
0
)
{
available
=
0
;
break
;
}
}
}
if
(
available
)
{
available_snapshots
[
total
]
=
i
;
total
++
;
}
}
if
(
total
>
0
)
{
monitor_printf
(
mon
,
"%s
\n
"
,
bdrv_snapshot_dump
(
buf
,
sizeof
(
buf
),
NULL
));
for
(
i
=
0
;
i
<
total
;
i
++
)
{
sn
=
&
sn_tab
[
available_snapshots
[
i
]];
monitor_printf
(
mon
,
"%s
\n
"
,
bdrv_snapshot_dump
(
buf
,
sizeof
(
buf
),
sn
));
}
}
else
{
monitor_printf
(
mon
,
"There is no suitable snapshot available
\n
"
);
}
qemu_free
(
sn_tab
);
qemu_free
(
available_snapshots
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录