Skip to content

Commit 29e3509

Browse files
author
Linus Torvalds
committed
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>
1 parent b45e516 commit 29e3509

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

fs/splice.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
106106

107107
static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
108108
int nr_pages, unsigned long offset,
109-
unsigned long len)
109+
unsigned long len, unsigned int flags)
110110
{
111111
struct pipe_inode_info *info;
112112
int ret, do_wakeup, i;
@@ -159,6 +159,12 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
159159
break;
160160
}
161161

162+
if (flags & SPLICE_F_NONBLOCK) {
163+
if (!ret)
164+
ret = -EAGAIN;
165+
break;
166+
}
167+
162168
if (signal_pending(current)) {
163169
if (!ret)
164170
ret = -ERESTARTSYS;
@@ -191,7 +197,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
191197
}
192198

193199
static int __generic_file_splice_read(struct file *in, struct inode *pipe,
194-
size_t len)
200+
size_t len, unsigned int flags)
195201
{
196202
struct address_space *mapping = in->f_mapping;
197203
unsigned int offset, nr_pages;
@@ -279,7 +285,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
279285
* Now we splice them into the pipe..
280286
*/
281287
splice_them:
282-
return move_to_pipe(pipe, pages, i, offset, len);
288+
return move_to_pipe(pipe, pages, i, offset, len, flags);
283289
}
284290

285291
ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
@@ -291,14 +297,19 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
291297
ret = 0;
292298
spliced = 0;
293299
while (len) {
294-
ret = __generic_file_splice_read(in, pipe, len);
300+
ret = __generic_file_splice_read(in, pipe, len, flags);
295301

296302
if (ret <= 0)
297303
break;
298304

299305
in->f_pos += ret;
300306
len -= ret;
301307
spliced += ret;
308+
309+
if (!(flags & SPLICE_F_NONBLOCK))
310+
continue;
311+
ret = -EAGAIN;
312+
break;
302313
}
303314

304315
if (spliced)
@@ -527,6 +538,12 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
527538
break;
528539
}
529540

541+
if (flags & SPLICE_F_NONBLOCK) {
542+
if (!ret)
543+
ret = -EAGAIN;
544+
break;
545+
}
546+
530547
if (signal_pending(current)) {
531548
if (!ret)
532549
ret = -ERESTARTSYS;

include/linux/pipe_fs_i.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,8 @@ void free_pipe_info(struct inode* inode);
6060
* add the splice flags here.
6161
*/
6262
#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
63+
#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
64+
/* we may still block on the fd we splice */
65+
/* from/to, of course */
6366

6467
#endif

0 commit comments

Comments
 (0)