diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 31 |
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 | */ |
1296 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | 1296 | long 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; |