Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
221415d7
Commit
221415d7
authored
Mar 23, 2006
by
Jens Axboe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] relay: add sendfile() support
Signed-off-by:
Jens Axboe
<
axboe@suse.de
>
parent
b86ff981
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
115 additions
and
29 deletions
+115
-29
kernel/relay.c
kernel/relay.c
+115
-29
No files found.
kernel/relay.c
View file @
221415d7
...
@@ -95,15 +95,16 @@ int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
...
@@ -95,15 +95,16 @@ int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
* @buf: the buffer struct
* @buf: the buffer struct
* @size: total size of the buffer
* @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
;
void
*
mem
;
unsigned
int
i
,
j
,
n_pages
;
unsigned
int
i
,
j
,
n_pages
;
size
=
PAGE_ALIGN
(
size
);
*
size
=
PAGE_ALIGN
(
*
size
);
n_pages
=
size
>>
PAGE_SHIFT
;
n_pages
=
*
size
>>
PAGE_SHIFT
;
buf
->
page_array
=
kcalloc
(
n_pages
,
sizeof
(
struct
page
*
),
GFP_KERNEL
);
buf
->
page_array
=
kcalloc
(
n_pages
,
sizeof
(
struct
page
*
),
GFP_KERNEL
);
if
(
!
buf
->
page_array
)
if
(
!
buf
->
page_array
)
...
@@ -118,7 +119,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
...
@@ -118,7 +119,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
if
(
!
mem
)
if
(
!
mem
)
goto
depopulate
;
goto
depopulate
;
memset
(
mem
,
0
,
size
);
memset
(
mem
,
0
,
*
size
);
buf
->
page_count
=
n_pages
;
buf
->
page_count
=
n_pages
;
return
mem
;
return
mem
;
...
@@ -146,7 +147,7 @@ struct rchan_buf *relay_create_buf(struct rchan *chan)
...
@@ -146,7 +147,7 @@ struct rchan_buf *relay_create_buf(struct rchan *chan)
if
(
!
buf
->
padding
)
if
(
!
buf
->
padding
)
goto
free_buf
;
goto
free_buf
;
buf
->
start
=
relay_alloc_buf
(
buf
,
chan
->
alloc_size
);
buf
->
start
=
relay_alloc_buf
(
buf
,
&
chan
->
alloc_size
);
if
(
!
buf
->
start
)
if
(
!
buf
->
start
)
goto
free_buf
;
goto
free_buf
;
...
@@ -543,6 +544,9 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
...
@@ -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
;
old_subbuf
=
buf
->
subbufs_produced
%
buf
->
chan
->
n_subbufs
;
buf
->
padding
[
old_subbuf
]
=
buf
->
prev_padding
;
buf
->
padding
[
old_subbuf
]
=
buf
->
prev_padding
;
buf
->
subbufs_produced
++
;
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
))
{
if
(
waitqueue_active
(
&
buf
->
read_wait
))
{
PREPARE_WORK
(
&
buf
->
wake_readers
,
wakeup_readers
,
buf
);
PREPARE_WORK
(
&
buf
->
wake_readers
,
wakeup_readers
,
buf
);
schedule_delayed_work
(
&
buf
->
wake_readers
,
1
);
schedule_delayed_work
(
&
buf
->
wake_readers
,
1
);
...
@@ -757,37 +761,33 @@ static void relay_file_read_consume(struct rchan_buf *buf,
...
@@ -757,37 +761,33 @@ static void relay_file_read_consume(struct rchan_buf *buf,
*/
*/
static
int
relay_file_read_avail
(
struct
rchan_buf
*
buf
,
size_t
read_pos
)
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
subbuf_size
=
buf
->
chan
->
subbuf_size
;
size_t
n_subbufs
=
buf
->
chan
->
n_subbufs
;
size_t
n_subbufs
=
buf
->
chan
->
n_subbufs
;
size_t
produced
=
buf
->
subbufs_produced
%
n_subbufs
;
size_t
produced
=
buf
->
subbufs_produced
;
size_t
consumed
=
buf
->
subbufs_consumed
%
n_subbufs
;
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
(
unlikely
(
buf
->
offset
>
subbuf_size
))
{
if
((
produced
>
n_subbufs
)
&&
if
(
produced
==
consumed
)
(
produced
+
n_subbufs
-
consumed
<=
n_subbufs
))
return
0
;
produced
+=
n_subbufs
;
return
1
;
}
else
if
(
consumed
==
produced
)
{
if
(
buf
->
offset
>
subbuf_size
)
{
produced
+=
n_subbufs
;
if
(
buf
->
subbufs_produced
==
buf
->
subbufs_consumed
)
consumed
+=
n_subbufs
;
}
}
}
if
(
buf
->
offset
>
subbuf_size
)
if
(
unlikely
(
produced
-
consumed
>=
n_subbufs
))
{
bytes_produced
=
(
produced
-
1
)
*
subbuf_size
+
write_offset
;
consumed
=
(
produced
/
n_subbufs
)
*
n_subbufs
;
else
buf
->
subbufs_consumed
=
consumed
;
bytes_produced
=
produced
*
subbuf_size
+
write_offset
;
}
bytes_consumed
=
consumed
*
subbuf_size
+
buf
->
bytes_consumed
;
produced
=
(
produced
%
n_subbufs
)
*
subbuf_size
+
buf
->
offset
;
if
(
bytes_produced
==
bytes_consumed
)
consumed
=
(
consumed
%
n_subbufs
)
*
subbuf_size
+
buf
->
bytes_consumed
;
if
(
consumed
>
produced
)
produced
+=
n_subbufs
*
subbuf_size
;
if
(
consumed
==
produced
)
return
0
;
return
0
;
relay_file_read_consume
(
buf
,
read_pos
,
0
);
return
1
;
return
1
;
}
}
...
@@ -908,6 +908,91 @@ out:
...
@@ -908,6 +908,91 @@ out:
return
ret
;
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
=
{
struct
file_operations
relay_file_operations
=
{
.
open
=
relay_file_open
,
.
open
=
relay_file_open
,
.
poll
=
relay_file_poll
,
.
poll
=
relay_file_poll
,
...
@@ -915,5 +1000,6 @@ struct file_operations relay_file_operations = {
...
@@ -915,5 +1000,6 @@ struct file_operations relay_file_operations = {
.
read
=
relay_file_read
,
.
read
=
relay_file_read
,
.
llseek
=
no_llseek
,
.
llseek
=
no_llseek
,
.
release
=
relay_file_release
,
.
release
=
relay_file_release
,
.
sendfile
=
relay_file_sendfile
,
};
};
EXPORT_SYMBOL_GPL
(
relay_file_operations
);
EXPORT_SYMBOL_GPL
(
relay_file_operations
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment