Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
ae255e52
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,发现更多精彩内容 >>
提交
ae255e52
编写于
9月 08, 2011
作者:
P
Paolo Bonzini
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
nbd: switch to asynchronous operation
Signed-off-by:
N
Paolo Bonzini
<
pbonzini@redhat.com
>
上级
8c5135f9
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
131 addition
and
65 deletion
+131
-65
block/nbd.c
block/nbd.c
+123
-65
nbd.c
nbd.c
+8
-0
未找到文件。
block/nbd.c
浏览文件 @
ae255e52
...
...
@@ -47,13 +47,17 @@
#endif
typedef
struct
BDRVNBDState
{
CoMutex
lock
;
int
sock
;
uint32_t
nbdflags
;
off_t
size
;
size_t
blocksize
;
char
*
export_name
;
/* An NBD server may export several devices */
CoMutex
mutex
;
Coroutine
*
coroutine
;
struct
nbd_reply
reply
;
/* If it begins with '/', this is a UNIX domain socket. Otherwise,
* it's a string of the form <hostname|ip4|\[ip6\]>:port
*/
...
...
@@ -106,6 +110,95 @@ out:
return
err
;
}
static
void
nbd_coroutine_start
(
BDRVNBDState
*
s
,
struct
nbd_request
*
request
)
{
qemu_co_mutex_lock
(
&
s
->
mutex
);
s
->
coroutine
=
qemu_coroutine_self
();
request
->
handle
=
(
uint64_t
)(
intptr_t
)
s
;
}
static
int
nbd_have_request
(
void
*
opaque
)
{
BDRVNBDState
*
s
=
opaque
;
return
!!
s
->
coroutine
;
}
static
void
nbd_reply_ready
(
void
*
opaque
)
{
BDRVNBDState
*
s
=
opaque
;
if
(
s
->
reply
.
handle
==
0
)
{
/* No reply already in flight. Fetch a header. */
if
(
nbd_receive_reply
(
s
->
sock
,
&
s
->
reply
)
<
0
)
{
s
->
reply
.
handle
=
0
;
}
}
/* There's no need for a mutex on the receive side, because the
* handler acts as a synchronization point and ensures that only
* one coroutine is called until the reply finishes. */
if
(
s
->
coroutine
)
{
qemu_coroutine_enter
(
s
->
coroutine
,
NULL
);
}
}
static
void
nbd_restart_write
(
void
*
opaque
)
{
BDRVNBDState
*
s
=
opaque
;
qemu_coroutine_enter
(
s
->
coroutine
,
NULL
);
}
static
int
nbd_co_send_request
(
BDRVNBDState
*
s
,
struct
nbd_request
*
request
,
struct
iovec
*
iov
,
int
offset
)
{
int
rc
,
ret
;
qemu_aio_set_fd_handler
(
s
->
sock
,
nbd_reply_ready
,
nbd_restart_write
,
nbd_have_request
,
NULL
,
s
);
rc
=
nbd_send_request
(
s
->
sock
,
request
);
if
(
rc
!=
-
1
&&
iov
)
{
ret
=
qemu_co_sendv
(
s
->
sock
,
iov
,
request
->
len
,
offset
);
if
(
ret
!=
request
->
len
)
{
errno
=
-
EIO
;
rc
=
-
1
;
}
}
qemu_aio_set_fd_handler
(
s
->
sock
,
nbd_reply_ready
,
NULL
,
nbd_have_request
,
NULL
,
s
);
return
rc
;
}
static
void
nbd_co_receive_reply
(
BDRVNBDState
*
s
,
struct
nbd_request
*
request
,
struct
nbd_reply
*
reply
,
struct
iovec
*
iov
,
int
offset
)
{
int
ret
;
/* Wait until we're woken up by the read handler. */
qemu_coroutine_yield
();
*
reply
=
s
->
reply
;
if
(
reply
->
handle
!=
request
->
handle
)
{
reply
->
error
=
EIO
;
}
else
{
if
(
iov
&&
reply
->
error
==
0
)
{
ret
=
qemu_co_recvv
(
s
->
sock
,
iov
,
request
->
len
,
offset
);
if
(
ret
!=
request
->
len
)
{
reply
->
error
=
EIO
;
}
}
/* Tell the read handler to read another header. */
s
->
reply
.
handle
=
0
;
}
}
static
void
nbd_coroutine_end
(
BDRVNBDState
*
s
,
struct
nbd_request
*
request
)
{
s
->
coroutine
=
NULL
;
qemu_co_mutex_unlock
(
&
s
->
mutex
);
}
static
int
nbd_establish_connection
(
BlockDriverState
*
bs
)
{
BDRVNBDState
*
s
=
bs
->
opaque
;
...
...
@@ -135,8 +228,11 @@ static int nbd_establish_connection(BlockDriverState *bs)
return
-
errno
;
}
/* Now that we're connected, set the socket to be non-blocking */
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
socket_set_nonblock
(
sock
);
qemu_aio_set_fd_handler
(
s
->
sock
,
nbd_reply_ready
,
NULL
,
nbd_have_request
,
NULL
,
s
);
s
->
sock
=
sock
;
s
->
size
=
size
;
...
...
@@ -152,11 +248,11 @@ static void nbd_teardown_connection(BlockDriverState *bs)
struct
nbd_request
request
;
request
.
type
=
NBD_CMD_DISC
;
request
.
handle
=
(
uint64_t
)(
intptr_t
)
bs
;
request
.
from
=
0
;
request
.
len
=
0
;
nbd_send_request
(
s
->
sock
,
&
request
);
qemu_aio_set_fd_handler
(
s
->
sock
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
closesocket
(
s
->
sock
);
}
...
...
@@ -165,6 +261,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
BDRVNBDState
*
s
=
bs
->
opaque
;
int
result
;
qemu_co_mutex_init
(
&
s
->
mutex
);
/* Pop the config into our state object. Exit if invalid. */
result
=
nbd_config
(
s
,
filename
,
flags
);
if
(
result
!=
0
)
{
...
...
@@ -176,90 +274,50 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
*/
result
=
nbd_establish_connection
(
bs
);
qemu_co_mutex_init
(
&
s
->
lock
);
return
result
;
}
static
int
nbd_
read
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
uint8_t
*
buf
,
int
nb_sectors
)
static
int
nbd_
co_readv
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
int
nb_sectors
,
QEMUIOVector
*
qiov
)
{
BDRVNBDState
*
s
=
bs
->
opaque
;
struct
nbd_request
request
;
struct
nbd_reply
reply
;
request
.
type
=
NBD_CMD_READ
;
request
.
handle
=
(
uint64_t
)(
intptr_t
)
bs
;
request
.
from
=
sector_num
*
512
;
request
.
len
=
nb_sectors
*
512
;
if
(
nbd_send_request
(
s
->
sock
,
&
request
)
==
-
1
)
return
-
errno
;
if
(
nbd_receive_reply
(
s
->
sock
,
&
reply
)
==
-
1
)
return
-
errno
;
if
(
reply
.
error
!=
0
)
return
-
reply
.
error
;
if
(
reply
.
handle
!=
request
.
handle
)
return
-
EIO
;
if
(
nbd_wr_sync
(
s
->
sock
,
buf
,
request
.
len
,
1
)
!=
request
.
len
)
return
-
EIO
;
nbd_coroutine_start
(
s
,
&
request
);
if
(
nbd_co_send_request
(
s
,
&
request
,
NULL
,
0
)
==
-
1
)
{
reply
.
error
=
errno
;
}
else
{
nbd_co_receive_reply
(
s
,
&
request
,
&
reply
,
qiov
->
iov
,
0
);
}
nbd_coroutine_end
(
s
,
&
request
);
return
-
reply
.
error
;
return
0
;
}
static
int
nbd_
write
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
const
uint8_t
*
buf
,
int
nb_sectors
)
static
int
nbd_
co_writev
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
int
nb_sectors
,
QEMUIOVector
*
qiov
)
{
BDRVNBDState
*
s
=
bs
->
opaque
;
struct
nbd_request
request
;
struct
nbd_reply
reply
;
request
.
type
=
NBD_CMD_WRITE
;
request
.
handle
=
(
uint64_t
)(
intptr_t
)
bs
;
request
.
from
=
sector_num
*
512
;
request
.
len
=
nb_sectors
*
512
;
if
(
nbd_send_request
(
s
->
sock
,
&
request
)
==
-
1
)
return
-
errno
;
if
(
nbd_wr_sync
(
s
->
sock
,
(
uint8_t
*
)
buf
,
request
.
len
,
0
)
!=
request
.
len
)
return
-
EIO
;
if
(
nbd_receive_reply
(
s
->
sock
,
&
reply
)
==
-
1
)
return
-
errno
;
if
(
reply
.
error
!=
0
)
return
-
reply
.
error
;
if
(
reply
.
handle
!=
request
.
handle
)
return
-
EIO
;
return
0
;
}
static
coroutine_fn
int
nbd_co_read
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
uint8_t
*
buf
,
int
nb_sectors
)
{
int
ret
;
BDRVNBDState
*
s
=
bs
->
opaque
;
qemu_co_mutex_lock
(
&
s
->
lock
);
ret
=
nbd_read
(
bs
,
sector_num
,
buf
,
nb_sectors
);
qemu_co_mutex_unlock
(
&
s
->
lock
);
return
ret
;
}
static
coroutine_fn
int
nbd_co_write
(
BlockDriverState
*
bs
,
int64_t
sector_num
,
const
uint8_t
*
buf
,
int
nb_sectors
)
{
int
ret
;
BDRVNBDState
*
s
=
bs
->
opaque
;
qemu_co_mutex_lock
(
&
s
->
lock
);
ret
=
nbd_write
(
bs
,
sector_num
,
buf
,
nb_sectors
);
qemu_co_mutex_unlock
(
&
s
->
lock
);
return
ret
;
nbd_coroutine_start
(
s
,
&
request
);
if
(
nbd_co_send_request
(
s
,
&
request
,
qiov
->
iov
,
0
)
==
-
1
)
{
reply
.
error
=
errno
;
}
else
{
nbd_co_receive_reply
(
s
,
&
request
,
&
reply
,
NULL
,
0
);
}
nbd_coroutine_end
(
s
,
&
request
);
return
-
reply
.
error
;
}
static
void
nbd_close
(
BlockDriverState
*
bs
)
...
...
@@ -282,8 +340,8 @@ static BlockDriver bdrv_nbd = {
.
format_name
=
"nbd"
,
.
instance_size
=
sizeof
(
BDRVNBDState
),
.
bdrv_file_open
=
nbd_open
,
.
bdrv_
read
=
nbd_co_read
,
.
bdrv_
write
=
nbd_co_write
,
.
bdrv_
co_readv
=
nbd_co_readv
,
.
bdrv_
co_writev
=
nbd_co_writev
,
.
bdrv_close
=
nbd_close
,
.
bdrv_getlength
=
nbd_getlength
,
.
protocol_name
=
"nbd"
,
...
...
nbd.c
浏览文件 @
ae255e52
...
...
@@ -81,6 +81,14 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
{
size_t
offset
=
0
;
if
(
qemu_in_coroutine
())
{
if
(
do_read
)
{
return
qemu_co_recv
(
fd
,
buffer
,
size
);
}
else
{
return
qemu_co_send
(
fd
,
buffer
,
size
);
}
}
while
(
offset
<
size
)
{
ssize_t
len
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录