Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
221415d7
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
221415d7
编写于
3月 23, 2006
作者:
J
Jens Axboe
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[PATCH] relay: add sendfile() support
Signed-off-by:
N
Jens Axboe
<
axboe@suse.de
>
上级
b86ff981
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
115 addition
and
29 deletion
+115
-29
kernel/relay.c
kernel/relay.c
+115
-29
未找到文件。
kernel/relay.c
浏览文件 @
221415d7
...
...
@@ -95,15 +95,16 @@ int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
* @buf: the buffer struct
* @size: total size of the buffer
*
* Returns a pointer to the resulting buffer, NULL if unsuccessful
* Returns a pointer to the resulting buffer, NULL if unsuccessful. The
* passed in size will get page aligned, if it isn't already.
*/
static
void
*
relay_alloc_buf
(
struct
rchan_buf
*
buf
,
unsigned
long
size
)
static
void
*
relay_alloc_buf
(
struct
rchan_buf
*
buf
,
size_t
*
size
)
{
void
*
mem
;
unsigned
int
i
,
j
,
n_pages
;
size
=
PAGE_ALIGN
(
size
);
n_pages
=
size
>>
PAGE_SHIFT
;
*
size
=
PAGE_ALIGN
(
*
size
);
n_pages
=
*
size
>>
PAGE_SHIFT
;
buf
->
page_array
=
kcalloc
(
n_pages
,
sizeof
(
struct
page
*
),
GFP_KERNEL
);
if
(
!
buf
->
page_array
)
...
...
@@ -118,7 +119,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
if
(
!
mem
)
goto
depopulate
;
memset
(
mem
,
0
,
size
);
memset
(
mem
,
0
,
*
size
);
buf
->
page_count
=
n_pages
;
return
mem
;
...
...
@@ -146,7 +147,7 @@ struct rchan_buf *relay_create_buf(struct rchan *chan)
if
(
!
buf
->
padding
)
goto
free_buf
;
buf
->
start
=
relay_alloc_buf
(
buf
,
chan
->
alloc_size
);
buf
->
start
=
relay_alloc_buf
(
buf
,
&
chan
->
alloc_size
);
if
(
!
buf
->
start
)
goto
free_buf
;
...
...
@@ -543,6 +544,9 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
old_subbuf
=
buf
->
subbufs_produced
%
buf
->
chan
->
n_subbufs
;
buf
->
padding
[
old_subbuf
]
=
buf
->
prev_padding
;
buf
->
subbufs_produced
++
;
buf
->
dentry
->
d_inode
->
i_size
+=
buf
->
chan
->
subbuf_size
-
buf
->
padding
[
old_subbuf
];
smp_mb
();
if
(
waitqueue_active
(
&
buf
->
read_wait
))
{
PREPARE_WORK
(
&
buf
->
wake_readers
,
wakeup_readers
,
buf
);
schedule_delayed_work
(
&
buf
->
wake_readers
,
1
);
...
...
@@ -757,36 +761,32 @@ static void relay_file_read_consume(struct rchan_buf *buf,
*/
static
int
relay_file_read_avail
(
struct
rchan_buf
*
buf
,
size_t
read_pos
)
{
size_t
bytes_produced
,
bytes_consumed
,
write_offset
;
size_t
subbuf_size
=
buf
->
chan
->
subbuf_size
;
size_t
n_subbufs
=
buf
->
chan
->
n_subbufs
;
size_t
produced
=
buf
->
subbufs_produced
%
n_subbufs
;
size_t
consumed
=
buf
->
subbufs_consumed
%
n_subbufs
;
size_t
produced
=
buf
->
subbufs_produced
;
size_t
consumed
=
buf
->
subbufs_consumed
;
write_offset
=
buf
->
offset
>
subbuf_size
?
subbuf_size
:
buf
->
offset
;
relay_file_read_consume
(
buf
,
read_pos
,
0
)
;
if
(
consumed
>
produced
)
{
if
((
produced
>
n_subbufs
)
&&
(
produced
+
n_subbufs
-
consumed
<=
n_subbufs
))
produced
+=
n_subbufs
;
}
else
if
(
consumed
==
produced
)
{
if
(
buf
->
offset
>
subbuf_size
)
{
produced
+=
n_subbufs
;
if
(
buf
->
subbufs_produced
==
buf
->
subbufs_consumed
)
consumed
+=
n_subbufs
;
if
(
unlikely
(
buf
->
offset
>
subbuf_size
))
{
if
(
produced
==
consumed
)
return
0
;
return
1
;
}
if
(
unlikely
(
produced
-
consumed
>=
n_subbufs
))
{
consumed
=
(
produced
/
n_subbufs
)
*
n_subbufs
;
buf
->
subbufs_consumed
=
consumed
;
}
if
(
buf
->
offset
>
subbuf_size
)
bytes_produced
=
(
produced
-
1
)
*
subbuf_size
+
write_offset
;
else
bytes_produced
=
produced
*
subbuf_size
+
write_offset
;
bytes_consumed
=
consumed
*
subbuf_size
+
buf
->
bytes_consumed
;
produced
=
(
produced
%
n_subbufs
)
*
subbuf_size
+
buf
->
offset
;
consumed
=
(
consumed
%
n_subbufs
)
*
subbuf_size
+
buf
->
bytes_consumed
;
if
(
bytes_produced
==
bytes_consum
ed
)
return
0
;
if
(
consumed
>
produc
ed
)
produced
+=
n_subbufs
*
subbuf_size
;
relay_file_read_consume
(
buf
,
read_pos
,
0
);
if
(
consumed
==
produced
)
return
0
;
return
1
;
}
...
...
@@ -908,6 +908,91 @@ static ssize_t relay_file_read(struct file *filp,
return
ret
;
}
static
ssize_t
relay_file_sendsubbuf
(
struct
file
*
filp
,
loff_t
*
ppos
,
size_t
count
,
read_actor_t
actor
,
void
*
target
)
{
struct
rchan_buf
*
buf
=
filp
->
private_data
;
read_descriptor_t
desc
;
size_t
read_start
,
avail
;
unsigned
long
pidx
,
poff
;
unsigned
int
subbuf_pages
;
ssize_t
ret
=
0
;
if
(
!
relay_file_read_avail
(
buf
,
*
ppos
))
return
0
;
read_start
=
relay_file_read_start_pos
(
*
ppos
,
buf
);
avail
=
relay_file_read_subbuf_avail
(
read_start
,
buf
);
if
(
!
avail
)
return
0
;
count
=
min
(
count
,
avail
);
desc
.
written
=
0
;
desc
.
count
=
count
;
desc
.
arg
.
data
=
target
;
desc
.
error
=
0
;
subbuf_pages
=
buf
->
chan
->
alloc_size
>>
PAGE_SHIFT
;
pidx
=
(
read_start
/
PAGE_SIZE
)
%
subbuf_pages
;
poff
=
read_start
&
~
PAGE_MASK
;
while
(
count
)
{
struct
page
*
p
=
buf
->
page_array
[
pidx
];
unsigned
int
len
;
len
=
PAGE_SIZE
-
poff
;
if
(
len
>
count
)
len
=
count
;
len
=
actor
(
&
desc
,
p
,
poff
,
len
);
if
(
desc
.
error
)
{
if
(
!
ret
)
ret
=
desc
.
error
;
break
;
}
count
-=
len
;
ret
+=
len
;
poff
=
0
;
pidx
=
(
pidx
+
1
)
%
subbuf_pages
;
}
if
(
ret
>
0
)
{
relay_file_read_consume
(
buf
,
read_start
,
ret
);
*
ppos
=
relay_file_read_end_pos
(
buf
,
read_start
,
ret
);
}
return
ret
;
}
static
ssize_t
relay_file_sendfile
(
struct
file
*
filp
,
loff_t
*
ppos
,
size_t
count
,
read_actor_t
actor
,
void
*
target
)
{
ssize_t
sent
=
0
,
ret
=
0
;
if
(
!
count
)
return
0
;
mutex_lock
(
&
filp
->
f_dentry
->
d_inode
->
i_mutex
);
do
{
ret
=
relay_file_sendsubbuf
(
filp
,
ppos
,
count
,
actor
,
target
);
if
(
ret
<
0
)
{
if
(
!
sent
)
sent
=
ret
;
break
;
}
count
-=
ret
;
sent
+=
ret
;
}
while
(
count
&&
ret
);
mutex_unlock
(
&
filp
->
f_dentry
->
d_inode
->
i_mutex
);
return
sent
;
}
struct
file_operations
relay_file_operations
=
{
.
open
=
relay_file_open
,
.
poll
=
relay_file_poll
,
...
...
@@ -915,5 +1000,6 @@ struct file_operations relay_file_operations = {
.
read
=
relay_file_read
,
.
llseek
=
no_llseek
,
.
release
=
relay_file_release
,
.
sendfile
=
relay_file_sendfile
,
};
EXPORT_SYMBOL_GPL
(
relay_file_operations
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录