diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/fs/splice.c b/fs/splice.c index 7394e9e17534..9313b6124a2e 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/syscalls.h> | 30 | #include <linux/syscalls.h> |
31 | #include <linux/uio.h> | 31 | #include <linux/uio.h> |
32 | #include <linux/security.h> | 32 | #include <linux/security.h> |
33 | #include <linux/gfp.h> | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * Attempt to steal a page from a pipe buffer. This should perhaps go into | 36 | * Attempt to steal a page from a pipe buffer. This should perhaps go into |
@@ -648,9 +649,11 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe, | |||
648 | ret = buf->ops->confirm(pipe, buf); | 649 | ret = buf->ops->confirm(pipe, buf); |
649 | if (!ret) { | 650 | if (!ret) { |
650 | more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; | 651 | more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; |
651 | 652 | if (file->f_op && file->f_op->sendpage) | |
652 | ret = file->f_op->sendpage(file, buf->page, buf->offset, | 653 | ret = file->f_op->sendpage(file, buf->page, buf->offset, |
653 | sd->len, &pos, more); | 654 | sd->len, &pos, more); |
655 | else | ||
656 | ret = -EINVAL; | ||
654 | } | 657 | } |
655 | 658 | ||
656 | return ret; | 659 | return ret; |
@@ -1068,8 +1071,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
1068 | if (unlikely(ret < 0)) | 1071 | if (unlikely(ret < 0)) |
1069 | return ret; | 1072 | return ret; |
1070 | 1073 | ||
1071 | splice_write = out->f_op->splice_write; | 1074 | if (out->f_op && out->f_op->splice_write) |
1072 | if (!splice_write) | 1075 | splice_write = out->f_op->splice_write; |
1076 | else | ||
1073 | splice_write = default_file_splice_write; | 1077 | splice_write = default_file_splice_write; |
1074 | 1078 | ||
1075 | return splice_write(pipe, out, ppos, len, flags); | 1079 | return splice_write(pipe, out, ppos, len, flags); |
@@ -1093,8 +1097,9 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
1093 | if (unlikely(ret < 0)) | 1097 | if (unlikely(ret < 0)) |
1094 | return ret; | 1098 | return ret; |
1095 | 1099 | ||
1096 | splice_read = in->f_op->splice_read; | 1100 | if (in->f_op && in->f_op->splice_read) |
1097 | if (!splice_read) | 1101 | splice_read = in->f_op->splice_read; |
1102 | else | ||
1098 | splice_read = default_file_splice_read; | 1103 | splice_read = default_file_splice_read; |
1099 | 1104 | ||
1100 | return splice_read(in, ppos, pipe, len, flags); | 1105 | return splice_read(in, ppos, pipe, len, flags); |
@@ -1316,7 +1321,8 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1316 | if (off_in) | 1321 | if (off_in) |
1317 | return -ESPIPE; | 1322 | return -ESPIPE; |
1318 | if (off_out) { | 1323 | if (off_out) { |
1319 | if (out->f_op->llseek == no_llseek) | 1324 | if (!out->f_op || !out->f_op->llseek || |
1325 | out->f_op->llseek == no_llseek) | ||
1320 | return -EINVAL; | 1326 | return -EINVAL; |
1321 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) | 1327 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) |
1322 | return -EFAULT; | 1328 | return -EFAULT; |
@@ -1336,7 +1342,8 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1336 | if (off_out) | 1342 | if (off_out) |
1337 | return -ESPIPE; | 1343 | return -ESPIPE; |
1338 | if (off_in) { | 1344 | if (off_in) { |
1339 | if (in->f_op->llseek == no_llseek) | 1345 | if (!in->f_op || !in->f_op->llseek || |
1346 | in->f_op->llseek == no_llseek) | ||
1340 | return -EINVAL; | 1347 | return -EINVAL; |
1341 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) | 1348 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) |
1342 | return -EFAULT; | 1349 | return -EFAULT; |