Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
8bd39456
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 大约 4 年
通知
14
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
8bd39456
编写于
7月 02, 2010
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'vhost-net' of
git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
上级
58eba97d
7b3384fc
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
58 addition
and
48 deletion
+58
-48
drivers/vhost/net.c
drivers/vhost/net.c
+10
-2
drivers/vhost/vhost.c
drivers/vhost/vhost.c
+44
-42
drivers/vhost/vhost.h
drivers/vhost/vhost.h
+4
-4
未找到文件。
drivers/vhost/net.c
浏览文件 @
8bd39456
...
@@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
...
@@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
static
void
handle_tx
(
struct
vhost_net
*
net
)
static
void
handle_tx
(
struct
vhost_net
*
net
)
{
{
struct
vhost_virtqueue
*
vq
=
&
net
->
dev
.
vqs
[
VHOST_NET_VQ_TX
];
struct
vhost_virtqueue
*
vq
=
&
net
->
dev
.
vqs
[
VHOST_NET_VQ_TX
];
unsigned
head
,
out
,
in
,
s
;
unsigned
out
,
in
,
s
;
int
head
;
struct
msghdr
msg
=
{
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_name
=
NULL
,
.
msg_namelen
=
0
,
.
msg_namelen
=
0
,
...
@@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net)
...
@@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net)
ARRAY_SIZE
(
vq
->
iov
),
ARRAY_SIZE
(
vq
->
iov
),
&
out
,
&
in
,
&
out
,
&
in
,
NULL
,
NULL
);
NULL
,
NULL
);
/* On error, stop handling until the next kick. */
if
(
unlikely
(
head
<
0
))
break
;
/* Nothing new? Wait for eventfd to tell us they refilled. */
/* Nothing new? Wait for eventfd to tell us they refilled. */
if
(
head
==
vq
->
num
)
{
if
(
head
==
vq
->
num
)
{
wmem
=
atomic_read
(
&
sock
->
sk
->
sk_wmem_alloc
);
wmem
=
atomic_read
(
&
sock
->
sk
->
sk_wmem_alloc
);
...
@@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net)
...
@@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net)
static
void
handle_rx
(
struct
vhost_net
*
net
)
static
void
handle_rx
(
struct
vhost_net
*
net
)
{
{
struct
vhost_virtqueue
*
vq
=
&
net
->
dev
.
vqs
[
VHOST_NET_VQ_RX
];
struct
vhost_virtqueue
*
vq
=
&
net
->
dev
.
vqs
[
VHOST_NET_VQ_RX
];
unsigned
head
,
out
,
in
,
log
,
s
;
unsigned
out
,
in
,
log
,
s
;
int
head
;
struct
vhost_log
*
vq_log
;
struct
vhost_log
*
vq_log
;
struct
msghdr
msg
=
{
struct
msghdr
msg
=
{
.
msg_name
=
NULL
,
.
msg_name
=
NULL
,
...
@@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net)
...
@@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net)
ARRAY_SIZE
(
vq
->
iov
),
ARRAY_SIZE
(
vq
->
iov
),
&
out
,
&
in
,
&
out
,
&
in
,
vq_log
,
&
log
);
vq_log
,
&
log
);
/* On error, stop handling until the next kick. */
if
(
unlikely
(
head
<
0
))
break
;
/* OK, now we need to know about added descriptors. */
/* OK, now we need to know about added descriptors. */
if
(
head
==
vq
->
num
)
{
if
(
head
==
vq
->
num
)
{
if
(
unlikely
(
vhost_enable_notify
(
vq
)))
{
if
(
unlikely
(
vhost_enable_notify
(
vq
)))
{
...
...
drivers/vhost/vhost.c
浏览文件 @
8bd39456
...
@@ -736,12 +736,12 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
...
@@ -736,12 +736,12 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
mem
=
rcu_dereference
(
dev
->
memory
);
mem
=
rcu_dereference
(
dev
->
memory
);
while
((
u64
)
len
>
s
)
{
while
((
u64
)
len
>
s
)
{
u64
size
;
u64
size
;
if
(
ret
>=
iov_size
)
{
if
(
unlikely
(
ret
>=
iov_size
)
)
{
ret
=
-
ENOBUFS
;
ret
=
-
ENOBUFS
;
break
;
break
;
}
}
reg
=
find_region
(
mem
,
addr
,
len
);
reg
=
find_region
(
mem
,
addr
,
len
);
if
(
!
reg
)
{
if
(
unlikely
(
!
reg
)
)
{
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
break
;
break
;
}
}
...
@@ -780,18 +780,18 @@ static unsigned next_desc(struct vring_desc *desc)
...
@@ -780,18 +780,18 @@ static unsigned next_desc(struct vring_desc *desc)
return
next
;
return
next
;
}
}
static
unsigned
get_indirect
(
struct
vhost_dev
*
dev
,
struct
vhost_virtqueue
*
vq
,
static
int
get_indirect
(
struct
vhost_dev
*
dev
,
struct
vhost_virtqueue
*
vq
,
struct
iovec
iov
[],
unsigned
int
iov_size
,
struct
iovec
iov
[],
unsigned
int
iov_size
,
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
struct
vhost_log
*
log
,
unsigned
int
*
log_num
,
struct
vhost_log
*
log
,
unsigned
int
*
log_num
,
struct
vring_desc
*
indirect
)
struct
vring_desc
*
indirect
)
{
{
struct
vring_desc
desc
;
struct
vring_desc
desc
;
unsigned
int
i
=
0
,
count
,
found
=
0
;
unsigned
int
i
=
0
,
count
,
found
=
0
;
int
ret
;
int
ret
;
/* Sanity check */
/* Sanity check */
if
(
indirect
->
len
%
sizeof
desc
)
{
if
(
unlikely
(
indirect
->
len
%
sizeof
desc
)
)
{
vq_err
(
vq
,
"Invalid length in indirect descriptor: "
vq_err
(
vq
,
"Invalid length in indirect descriptor: "
"len 0x%llx not multiple of 0x%zx
\n
"
,
"len 0x%llx not multiple of 0x%zx
\n
"
,
(
unsigned
long
long
)
indirect
->
len
,
(
unsigned
long
long
)
indirect
->
len
,
...
@@ -801,7 +801,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -801,7 +801,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
ret
=
translate_desc
(
dev
,
indirect
->
addr
,
indirect
->
len
,
vq
->
indirect
,
ret
=
translate_desc
(
dev
,
indirect
->
addr
,
indirect
->
len
,
vq
->
indirect
,
ARRAY_SIZE
(
vq
->
indirect
));
ARRAY_SIZE
(
vq
->
indirect
));
if
(
ret
<
0
)
{
if
(
unlikely
(
ret
<
0
)
)
{
vq_err
(
vq
,
"Translation failure %d in indirect.
\n
"
,
ret
);
vq_err
(
vq
,
"Translation failure %d in indirect.
\n
"
,
ret
);
return
ret
;
return
ret
;
}
}
...
@@ -813,7 +813,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -813,7 +813,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
count
=
indirect
->
len
/
sizeof
desc
;
count
=
indirect
->
len
/
sizeof
desc
;
/* Buffers are chained via a 16 bit next field, so
/* Buffers are chained via a 16 bit next field, so
* we can have at most 2^16 of these. */
* we can have at most 2^16 of these. */
if
(
count
>
USHRT_MAX
+
1
)
{
if
(
unlikely
(
count
>
USHRT_MAX
+
1
)
)
{
vq_err
(
vq
,
"Indirect buffer length too big: %d
\n
"
,
vq_err
(
vq
,
"Indirect buffer length too big: %d
\n
"
,
indirect
->
len
);
indirect
->
len
);
return
-
E2BIG
;
return
-
E2BIG
;
...
@@ -821,19 +821,19 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -821,19 +821,19 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
do
{
do
{
unsigned
iov_count
=
*
in_num
+
*
out_num
;
unsigned
iov_count
=
*
in_num
+
*
out_num
;
if
(
++
found
>
count
)
{
if
(
unlikely
(
++
found
>
count
)
)
{
vq_err
(
vq
,
"Loop detected: last one at %u "
vq_err
(
vq
,
"Loop detected: last one at %u "
"indirect size %u
\n
"
,
"indirect size %u
\n
"
,
i
,
count
);
i
,
count
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
memcpy_fromiovec
((
unsigned
char
*
)
&
desc
,
vq
->
indirect
,
if
(
unlikely
(
memcpy_fromiovec
((
unsigned
char
*
)
&
desc
,
vq
->
indirect
,
sizeof
desc
))
{
sizeof
desc
)
))
{
vq_err
(
vq
,
"Failed indirect descriptor: idx %d, %zx
\n
"
,
vq_err
(
vq
,
"Failed indirect descriptor: idx %d, %zx
\n
"
,
i
,
(
size_t
)
indirect
->
addr
+
i
*
sizeof
desc
);
i
,
(
size_t
)
indirect
->
addr
+
i
*
sizeof
desc
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
desc
.
flags
&
VRING_DESC_F_INDIRECT
)
{
if
(
unlikely
(
desc
.
flags
&
VRING_DESC_F_INDIRECT
)
)
{
vq_err
(
vq
,
"Nested indirect descriptor: idx %d, %zx
\n
"
,
vq_err
(
vq
,
"Nested indirect descriptor: idx %d, %zx
\n
"
,
i
,
(
size_t
)
indirect
->
addr
+
i
*
sizeof
desc
);
i
,
(
size_t
)
indirect
->
addr
+
i
*
sizeof
desc
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -841,7 +841,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -841,7 +841,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
ret
=
translate_desc
(
dev
,
desc
.
addr
,
desc
.
len
,
iov
+
iov_count
,
ret
=
translate_desc
(
dev
,
desc
.
addr
,
desc
.
len
,
iov
+
iov_count
,
iov_size
-
iov_count
);
iov_size
-
iov_count
);
if
(
ret
<
0
)
{
if
(
unlikely
(
ret
<
0
)
)
{
vq_err
(
vq
,
"Translation failure %d indirect idx %d
\n
"
,
vq_err
(
vq
,
"Translation failure %d indirect idx %d
\n
"
,
ret
,
i
);
ret
,
i
);
return
ret
;
return
ret
;
...
@@ -857,7 +857,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -857,7 +857,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
}
else
{
}
else
{
/* If it's an output descriptor, they're all supposed
/* If it's an output descriptor, they're all supposed
* to come before any input descriptors. */
* to come before any input descriptors. */
if
(
*
in_num
)
{
if
(
unlikely
(
*
in_num
)
)
{
vq_err
(
vq
,
"Indirect descriptor "
vq_err
(
vq
,
"Indirect descriptor "
"has out after in: idx %d
\n
"
,
i
);
"has out after in: idx %d
\n
"
,
i
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
* number of output then some number of input descriptors, it's actually two
* number of output then some number of input descriptors, it's actually two
* iovecs, but we pack them into one and note how many of each there were.
* iovecs, but we pack them into one and note how many of each there were.
*
*
* This function returns the descriptor number found, or vq->num (which
* This function returns the descriptor number found, or vq->num (which is
* is never a valid descriptor number) if none was found. */
* never a valid descriptor number) if none was found. A negative code is
unsigned
vhost_get_vq_desc
(
struct
vhost_dev
*
dev
,
struct
vhost_virtqueue
*
vq
,
* returned on error. */
struct
iovec
iov
[],
unsigned
int
iov_size
,
int
vhost_get_vq_desc
(
struct
vhost_dev
*
dev
,
struct
vhost_virtqueue
*
vq
,
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
struct
iovec
iov
[],
unsigned
int
iov_size
,
struct
vhost_log
*
log
,
unsigned
int
*
log_num
)
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
struct
vhost_log
*
log
,
unsigned
int
*
log_num
)
{
{
struct
vring_desc
desc
;
struct
vring_desc
desc
;
unsigned
int
i
,
head
,
found
=
0
;
unsigned
int
i
,
head
,
found
=
0
;
...
@@ -887,16 +888,16 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -887,16 +888,16 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
/* Check it isn't doing very strange things with descriptor numbers. */
/* Check it isn't doing very strange things with descriptor numbers. */
last_avail_idx
=
vq
->
last_avail_idx
;
last_avail_idx
=
vq
->
last_avail_idx
;
if
(
get_user
(
vq
->
avail_idx
,
&
vq
->
avail
->
idx
))
{
if
(
unlikely
(
get_user
(
vq
->
avail_idx
,
&
vq
->
avail
->
idx
)
))
{
vq_err
(
vq
,
"Failed to access avail idx at %p
\n
"
,
vq_err
(
vq
,
"Failed to access avail idx at %p
\n
"
,
&
vq
->
avail
->
idx
);
&
vq
->
avail
->
idx
);
return
vq
->
num
;
return
-
EFAULT
;
}
}
if
(
(
u16
)(
vq
->
avail_idx
-
last_avail_idx
)
>
vq
->
num
)
{
if
(
unlikely
((
u16
)(
vq
->
avail_idx
-
last_avail_idx
)
>
vq
->
num
)
)
{
vq_err
(
vq
,
"Guest moved used index from %u to %u"
,
vq_err
(
vq
,
"Guest moved used index from %u to %u"
,
last_avail_idx
,
vq
->
avail_idx
);
last_avail_idx
,
vq
->
avail_idx
);
return
vq
->
num
;
return
-
EFAULT
;
}
}
/* If there's nothing new since last we looked, return invalid. */
/* If there's nothing new since last we looked, return invalid. */
...
@@ -908,18 +909,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -908,18 +909,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
/* Grab the next descriptor number they're advertising, and increment
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
* the index we've seen. */
if
(
get_user
(
head
,
&
vq
->
avail
->
ring
[
last_avail_idx
%
vq
->
num
]))
{
if
(
unlikely
(
get_user
(
head
,
&
vq
->
avail
->
ring
[
last_avail_idx
%
vq
->
num
])))
{
vq_err
(
vq
,
"Failed to read head: idx %d address %p
\n
"
,
vq_err
(
vq
,
"Failed to read head: idx %d address %p
\n
"
,
last_avail_idx
,
last_avail_idx
,
&
vq
->
avail
->
ring
[
last_avail_idx
%
vq
->
num
]);
&
vq
->
avail
->
ring
[
last_avail_idx
%
vq
->
num
]);
return
vq
->
num
;
return
-
EFAULT
;
}
}
/* If their number is silly, that's an error. */
/* If their number is silly, that's an error. */
if
(
head
>=
vq
->
num
)
{
if
(
unlikely
(
head
>=
vq
->
num
)
)
{
vq_err
(
vq
,
"Guest says index %u > %u is available"
,
vq_err
(
vq
,
"Guest says index %u > %u is available"
,
head
,
vq
->
num
);
head
,
vq
->
num
);
return
vq
->
num
;
return
-
EINVAL
;
}
}
/* When we start there are none of either input nor output. */
/* When we start there are none of either input nor output. */
...
@@ -930,41 +932,41 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -930,41 +932,41 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
i
=
head
;
i
=
head
;
do
{
do
{
unsigned
iov_count
=
*
in_num
+
*
out_num
;
unsigned
iov_count
=
*
in_num
+
*
out_num
;
if
(
i
>=
vq
->
num
)
{
if
(
unlikely
(
i
>=
vq
->
num
)
)
{
vq_err
(
vq
,
"Desc index is %u > %u, head = %u"
,
vq_err
(
vq
,
"Desc index is %u > %u, head = %u"
,
i
,
vq
->
num
,
head
);
i
,
vq
->
num
,
head
);
return
vq
->
num
;
return
-
EINVAL
;
}
}
if
(
++
found
>
vq
->
num
)
{
if
(
unlikely
(
++
found
>
vq
->
num
)
)
{
vq_err
(
vq
,
"Loop detected: last one at %u "
vq_err
(
vq
,
"Loop detected: last one at %u "
"vq size %u head %u
\n
"
,
"vq size %u head %u
\n
"
,
i
,
vq
->
num
,
head
);
i
,
vq
->
num
,
head
);
return
vq
->
num
;
return
-
EINVAL
;
}
}
ret
=
copy_from_user
(
&
desc
,
vq
->
desc
+
i
,
sizeof
desc
);
ret
=
copy_from_user
(
&
desc
,
vq
->
desc
+
i
,
sizeof
desc
);
if
(
ret
)
{
if
(
unlikely
(
ret
)
)
{
vq_err
(
vq
,
"Failed to get descriptor: idx %d addr %p
\n
"
,
vq_err
(
vq
,
"Failed to get descriptor: idx %d addr %p
\n
"
,
i
,
vq
->
desc
+
i
);
i
,
vq
->
desc
+
i
);
return
vq
->
num
;
return
-
EFAULT
;
}
}
if
(
desc
.
flags
&
VRING_DESC_F_INDIRECT
)
{
if
(
desc
.
flags
&
VRING_DESC_F_INDIRECT
)
{
ret
=
get_indirect
(
dev
,
vq
,
iov
,
iov_size
,
ret
=
get_indirect
(
dev
,
vq
,
iov
,
iov_size
,
out_num
,
in_num
,
out_num
,
in_num
,
log
,
log_num
,
&
desc
);
log
,
log_num
,
&
desc
);
if
(
ret
<
0
)
{
if
(
unlikely
(
ret
<
0
)
)
{
vq_err
(
vq
,
"Failure detected "
vq_err
(
vq
,
"Failure detected "
"in indirect descriptor at idx %d
\n
"
,
i
);
"in indirect descriptor at idx %d
\n
"
,
i
);
return
vq
->
num
;
return
ret
;
}
}
continue
;
continue
;
}
}
ret
=
translate_desc
(
dev
,
desc
.
addr
,
desc
.
len
,
iov
+
iov_count
,
ret
=
translate_desc
(
dev
,
desc
.
addr
,
desc
.
len
,
iov
+
iov_count
,
iov_size
-
iov_count
);
iov_size
-
iov_count
);
if
(
ret
<
0
)
{
if
(
unlikely
(
ret
<
0
)
)
{
vq_err
(
vq
,
"Translation failure %d descriptor idx %d
\n
"
,
vq_err
(
vq
,
"Translation failure %d descriptor idx %d
\n
"
,
ret
,
i
);
ret
,
i
);
return
vq
->
num
;
return
ret
;
}
}
if
(
desc
.
flags
&
VRING_DESC_F_WRITE
)
{
if
(
desc
.
flags
&
VRING_DESC_F_WRITE
)
{
/* If this is an input descriptor,
/* If this is an input descriptor,
...
@@ -978,10 +980,10 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
...
@@ -978,10 +980,10 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
}
else
{
}
else
{
/* If it's an output descriptor, they're all supposed
/* If it's an output descriptor, they're all supposed
* to come before any input descriptors. */
* to come before any input descriptors. */
if
(
*
in_num
)
{
if
(
unlikely
(
*
in_num
)
)
{
vq_err
(
vq
,
"Descriptor has out after in: "
vq_err
(
vq
,
"Descriptor has out after in: "
"idx %d
\n
"
,
i
);
"idx %d
\n
"
,
i
);
return
vq
->
num
;
return
-
EINVAL
;
}
}
*
out_num
+=
ret
;
*
out_num
+=
ret
;
}
}
...
...
drivers/vhost/vhost.h
浏览文件 @
8bd39456
...
@@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
...
@@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
int
vhost_vq_access_ok
(
struct
vhost_virtqueue
*
vq
);
int
vhost_vq_access_ok
(
struct
vhost_virtqueue
*
vq
);
int
vhost_log_access_ok
(
struct
vhost_dev
*
);
int
vhost_log_access_ok
(
struct
vhost_dev
*
);
unsigned
vhost_get_vq_desc
(
struct
vhost_dev
*
,
struct
vhost_virtqueue
*
,
int
vhost_get_vq_desc
(
struct
vhost_dev
*
,
struct
vhost_virtqueue
*
,
struct
iovec
iov
[],
unsigned
int
iov_count
,
struct
iovec
iov
[],
unsigned
int
iov_count
,
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
unsigned
int
*
out_num
,
unsigned
int
*
in_num
,
struct
vhost_log
*
log
,
unsigned
int
*
log_num
);
struct
vhost_log
*
log
,
unsigned
int
*
log_num
);
void
vhost_discard_vq_desc
(
struct
vhost_virtqueue
*
);
void
vhost_discard_vq_desc
(
struct
vhost_virtqueue
*
);
int
vhost_add_used
(
struct
vhost_virtqueue
*
,
unsigned
int
head
,
int
len
);
int
vhost_add_used
(
struct
vhost_virtqueue
*
,
unsigned
int
head
,
int
len
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录