splice: add SPLICE_F_NONBLOCK flag
It doesn't make the splice itself necessarily nonblocking (because the actual file descriptors that are spliced from/to may block unless they have the O_NONBLOCK flag set), but it makes the splice pipe operations nonblocking. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
b45e516f70
Коммит
29e350944f
25
fs/splice.c
25
fs/splice.c
|
@ -106,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
|
|||
|
||||
static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
|
||||
int nr_pages, unsigned long offset,
|
||||
unsigned long len)
|
||||
unsigned long len, unsigned int flags)
|
||||
{
|
||||
struct pipe_inode_info *info;
|
||||
int ret, do_wakeup, i;
|
||||
|
@ -159,6 +159,12 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
|
|||
break;
|
||||
}
|
||||
|
||||
if (flags & SPLICE_F_NONBLOCK) {
|
||||
if (!ret)
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
if (!ret)
|
||||
ret = -ERESTARTSYS;
|
||||
|
@ -191,7 +197,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
|
|||
}
|
||||
|
||||
static int __generic_file_splice_read(struct file *in, struct inode *pipe,
|
||||
size_t len)
|
||||
size_t len, unsigned int flags)
|
||||
{
|
||||
struct address_space *mapping = in->f_mapping;
|
||||
unsigned int offset, nr_pages;
|
||||
|
@ -279,7 +285,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||
* Now we splice them into the pipe..
|
||||
*/
|
||||
splice_them:
|
||||
return move_to_pipe(pipe, pages, i, offset, len);
|
||||
return move_to_pipe(pipe, pages, i, offset, len, flags);
|
||||
}
|
||||
|
||||
ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
|
||||
|
@ -291,7 +297,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||
ret = 0;
|
||||
spliced = 0;
|
||||
while (len) {
|
||||
ret = __generic_file_splice_read(in, pipe, len);
|
||||
ret = __generic_file_splice_read(in, pipe, len, flags);
|
||||
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
@ -299,6 +305,11 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||
in->f_pos += ret;
|
||||
len -= ret;
|
||||
spliced += ret;
|
||||
|
||||
if (!(flags & SPLICE_F_NONBLOCK))
|
||||
continue;
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (spliced)
|
||||
|
@ -527,6 +538,12 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
|
|||
break;
|
||||
}
|
||||
|
||||
if (flags & SPLICE_F_NONBLOCK) {
|
||||
if (!ret)
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
if (!ret)
|
||||
ret = -ERESTARTSYS;
|
||||
|
|
|
@ -60,5 +60,8 @@ void free_pipe_info(struct inode* inode);
|
|||
* add the splice flags here.
|
||||
*/
|
||||
#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
|
||||
#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
|
||||
/* we may still block on the fd we splice */
|
||||
/* from/to, of course */
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче