aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/fs/splice.c b/fs/splice.c
index e6b25598c8c4..9eca476227d5 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1274,7 +1274,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
1274{ 1274{
1275 struct file *file = sd->u.file; 1275 struct file *file = sd->u.file;
1276 1276
1277 return do_splice_from(pipe, file, &file->f_pos, sd->total_len, 1277 return do_splice_from(pipe, file, sd->opos, sd->total_len,
1278 sd->flags); 1278 sd->flags);
1279} 1279}
1280 1280
@@ -1294,7 +1294,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
1294 * 1294 *
1295 */ 1295 */
1296long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, 1296long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
1297 size_t len, unsigned int flags) 1297 loff_t *opos, size_t len, unsigned int flags)
1298{ 1298{
1299 struct splice_desc sd = { 1299 struct splice_desc sd = {
1300 .len = len, 1300 .len = len,
@@ -1302,6 +1302,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
1302 .flags = flags, 1302 .flags = flags,
1303 .pos = *ppos, 1303 .pos = *ppos,
1304 .u.file = out, 1304 .u.file = out,
1305 .opos = opos,
1305 }; 1306 };
1306 long ret; 1307 long ret;
1307 1308
@@ -1325,7 +1326,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1325{ 1326{
1326 struct pipe_inode_info *ipipe; 1327 struct pipe_inode_info *ipipe;
1327 struct pipe_inode_info *opipe; 1328 struct pipe_inode_info *opipe;
1328 loff_t offset, *off; 1329 loff_t offset;
1329 long ret; 1330 long ret;
1330 1331
1331 ipipe = get_pipe_info(in); 1332 ipipe = get_pipe_info(in);
@@ -1356,13 +1357,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1356 return -EINVAL; 1357 return -EINVAL;
1357 if (copy_from_user(&offset, off_out, sizeof(loff_t))) 1358 if (copy_from_user(&offset, off_out, sizeof(loff_t)))
1358 return -EFAULT; 1359 return -EFAULT;
1359 off = &offset; 1360 } else {
1360 } else 1361 offset = out->f_pos;
1361 off = &out->f_pos; 1362 }
1362 1363
1363 ret = do_splice_from(ipipe, out, off, len, flags); 1364 ret = do_splice_from(ipipe, out, &offset, len, flags);
1364 1365
1365 if (off_out && copy_to_user(off_out, off, sizeof(loff_t))) 1366 if (!off_out)
1367 out->f_pos = offset;
1368 else if (copy_to_user(off_out, &offset, sizeof(loff_t)))
1366 ret = -EFAULT; 1369 ret = -EFAULT;
1367 1370
1368 return ret; 1371 return ret;
@@ -1376,13 +1379,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1376 return -EINVAL; 1379 return -EINVAL;
1377 if (copy_from_user(&offset, off_in, sizeof(loff_t))) 1380 if (copy_from_user(&offset, off_in, sizeof(loff_t)))
1378 return -EFAULT; 1381 return -EFAULT;
1379 off = &offset; 1382 } else {
1380 } else 1383 offset = in->f_pos;
1381 off = &in->f_pos; 1384 }
1382 1385
1383 ret = do_splice_to(in, off, opipe, len, flags); 1386 ret = do_splice_to(in, &offset, opipe, len, flags);
1384 1387
1385 if (off_in && copy_to_user(off_in, off, sizeof(loff_t))) 1388 if (!off_in)
1389 in->f_pos = offset;
1390 else if (copy_to_user(off_in, &offset, sizeof(loff_t)))
1386 ret = -EFAULT; 1391 ret = -EFAULT;
1387 1392
1388 return ret; 1393 return ret;