Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
db85a9eb
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
db85a9eb
编写于
8年前
作者:
A
Al Viro
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
splice: switch get_iovec_page_array() to iov_iter
Signed-off-by:
N
Al Viro
<
viro@zeniv.linux.org.uk
>
上级
e7c3c646
无相关合并请求
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
36 addition
and
99 deletion
+36
-99
fs/splice.c
fs/splice.c
+36
-99
未找到文件。
fs/splice.c
浏览文件 @
db85a9eb
...
...
@@ -1434,106 +1434,32 @@ static long do_splice(struct file *in, loff_t __user *off_in,
return
-
EINVAL
;
}
/*
* Map an iov into an array of pages and offset/length tupples. With the
* partial_page structure, we can map several non-contiguous ranges into
* our ones pages[] map instead of splitting that operation into pieces.
* Could easily be exported as a generic helper for other users, in which
* case one would probably want to add a 'max_nr_pages' parameter as well.
*/
static
int
get_iovec_page_array
(
const
struct
iovec
__user
*
iov
,
unsigned
int
nr_vecs
,
struct
page
**
pages
,
struct
partial_page
*
partial
,
bool
aligned
,
static
int
get_iovec_page_array
(
struct
iov_iter
*
from
,
struct
page
**
pages
,
struct
partial_page
*
partial
,
unsigned
int
pipe_buffers
)
{
int
buffers
=
0
,
error
=
0
;
while
(
nr_vecs
)
{
unsigned
long
off
,
npages
;
struct
iovec
entry
;
void
__user
*
base
;
size_t
len
;
int
i
;
error
=
-
EFAULT
;
if
(
copy_from_user
(
&
entry
,
iov
,
sizeof
(
entry
)))
break
;
base
=
entry
.
iov_base
;
len
=
entry
.
iov_len
;
/*
* Sanity check this iovec. 0 read succeeds.
*/
error
=
0
;
if
(
unlikely
(
!
len
))
break
;
error
=
-
EFAULT
;
if
(
!
access_ok
(
VERIFY_READ
,
base
,
len
))
break
;
/*
* Get this base offset and number of pages, then map
* in the user pages.
*/
off
=
(
unsigned
long
)
base
&
~
PAGE_MASK
;
/*
* If asked for alignment, the offset must be zero and the
* length a multiple of the PAGE_SIZE.
*/
error
=
-
EINVAL
;
if
(
aligned
&&
(
off
||
len
&
~
PAGE_MASK
))
break
;
npages
=
(
off
+
len
+
PAGE_SIZE
-
1
)
>>
PAGE_SHIFT
;
if
(
npages
>
pipe_buffers
-
buffers
)
npages
=
pipe_buffers
-
buffers
;
error
=
get_user_pages_fast
((
unsigned
long
)
base
,
npages
,
0
,
&
pages
[
buffers
]);
if
(
unlikely
(
error
<=
0
))
break
;
/*
* Fill this contiguous range into the partial page map.
*/
for
(
i
=
0
;
i
<
error
;
i
++
)
{
const
int
plen
=
min_t
(
size_t
,
len
,
PAGE_SIZE
-
off
);
partial
[
buffers
].
offset
=
off
;
partial
[
buffers
].
len
=
plen
;
off
=
0
;
len
-=
plen
;
int
buffers
=
0
;
while
(
iov_iter_count
(
from
))
{
ssize_t
copied
;
size_t
start
;
copied
=
iov_iter_get_pages
(
from
,
pages
+
buffers
,
~
0UL
,
pipe_buffers
-
buffers
,
&
start
);
if
(
copied
<=
0
)
return
buffers
?
buffers
:
copied
;
iov_iter_advance
(
from
,
copied
);
while
(
copied
)
{
int
size
=
min_t
(
int
,
copied
,
PAGE_SIZE
-
start
);
partial
[
buffers
].
offset
=
start
;
partial
[
buffers
].
len
=
size
;
copied
-=
size
;
start
=
0
;
buffers
++
;
}
/*
* We didn't complete this iov, stop here since it probably
* means we have to move some of this into a pipe to
* be able to continue.
*/
if
(
len
)
break
;
/*
* Don't continue if we mapped fewer pages than we asked for,
* or if we mapped the max number of pages that we have
* room for.
*/
if
(
error
<
npages
||
buffers
==
pipe_buffers
)
break
;
nr_vecs
--
;
iov
++
;
}
if
(
buffers
)
return
buffers
;
return
error
;
return
buffers
;
}
static
int
pipe_to_user
(
struct
pipe_inode_info
*
pipe
,
struct
pipe_buffer
*
buf
,
...
...
@@ -1587,10 +1513,13 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
* as splice-from-memory, where the regular splice is splice-from-file (or
* to file). In both cases the output is a pipe, naturally.
*/
static
long
vmsplice_to_pipe
(
struct
file
*
file
,
const
struct
iovec
__user
*
iov
,
static
long
vmsplice_to_pipe
(
struct
file
*
file
,
const
struct
iovec
__user
*
u
iov
,
unsigned
long
nr_segs
,
unsigned
int
flags
)
{
struct
pipe_inode_info
*
pipe
;
struct
iovec
iovstack
[
UIO_FASTIOV
];
struct
iovec
*
iov
=
iovstack
;
struct
iov_iter
from
;
struct
page
*
pages
[
PIPE_DEF_BUFFERS
];
struct
partial_page
partial
[
PIPE_DEF_BUFFERS
];
struct
splice_pipe_desc
spd
=
{
...
...
@@ -1607,11 +1536,18 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
if
(
!
pipe
)
return
-
EBADF
;
if
(
splice_grow_spd
(
pipe
,
&
spd
))
ret
=
import_iovec
(
WRITE
,
uiov
,
nr_segs
,
ARRAY_SIZE
(
iovstack
),
&
iov
,
&
from
);
if
(
ret
<
0
)
return
ret
;
if
(
splice_grow_spd
(
pipe
,
&
spd
))
{
kfree
(
iov
);
return
-
ENOMEM
;
}
spd
.
nr_pages
=
get_iovec_page_array
(
iov
,
nr_segs
,
spd
.
pages
,
spd
.
partial
,
false
,
spd
.
nr_pages
=
get_iovec_page_array
(
&
from
,
spd
.
pages
,
spd
.
partial
,
spd
.
nr_pages_max
);
if
(
spd
.
nr_pages
<=
0
)
ret
=
spd
.
nr_pages
;
...
...
@@ -1619,6 +1555,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
ret
=
splice_to_pipe
(
pipe
,
&
spd
);
splice_shrink_spd
(
&
spd
);
kfree
(
iov
);
return
ret
;
}
...
...
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
反馈
建议
客服
返回
顶部