Commit 7995bd287134f6c8f80d94bebe7396f05a9bc42b
1 parent
c9036e9f3b
Exists in
master
and in
20 other branches
splice: don't pass the address of ->f_pos to methods
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 5 changed files with 41 additions and 23 deletions Side-by-side Diff
fs/internal.h
... | ... | @@ -132,6 +132,12 @@ |
132 | 132 | extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); |
133 | 133 | |
134 | 134 | /* |
135 | + * splice.c | |
136 | + */ | |
137 | +extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |
138 | + loff_t *opos, size_t len, unsigned int flags); | |
139 | + | |
140 | +/* | |
135 | 141 | * pipe.c |
136 | 142 | */ |
137 | 143 | extern const struct file_operations pipefifo_fops; |
fs/read_write.c
... | ... | @@ -1064,6 +1064,7 @@ |
1064 | 1064 | struct fd in, out; |
1065 | 1065 | struct inode *in_inode, *out_inode; |
1066 | 1066 | loff_t pos; |
1067 | + loff_t out_pos; | |
1067 | 1068 | ssize_t retval; |
1068 | 1069 | int fl; |
1069 | 1070 | |
1070 | 1071 | |
... | ... | @@ -1077,12 +1078,14 @@ |
1077 | 1078 | if (!(in.file->f_mode & FMODE_READ)) |
1078 | 1079 | goto fput_in; |
1079 | 1080 | retval = -ESPIPE; |
1080 | - if (!ppos) | |
1081 | - ppos = &in.file->f_pos; | |
1082 | - else | |
1081 | + if (!ppos) { | |
1082 | + pos = in.file->f_pos; | |
1083 | + } else { | |
1084 | + pos = *ppos; | |
1083 | 1085 | if (!(in.file->f_mode & FMODE_PREAD)) |
1084 | 1086 | goto fput_in; |
1085 | - retval = rw_verify_area(READ, in.file, ppos, count); | |
1087 | + } | |
1088 | + retval = rw_verify_area(READ, in.file, &pos, count); | |
1086 | 1089 | if (retval < 0) |
1087 | 1090 | goto fput_in; |
1088 | 1091 | count = retval; |
... | ... | @@ -1099,7 +1102,8 @@ |
1099 | 1102 | retval = -EINVAL; |
1100 | 1103 | in_inode = file_inode(in.file); |
1101 | 1104 | out_inode = file_inode(out.file); |
1102 | - retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count); | |
1105 | + out_pos = out.file->f_pos; | |
1106 | + retval = rw_verify_area(WRITE, out.file, &out_pos, count); | |
1103 | 1107 | if (retval < 0) |
1104 | 1108 | goto fput_out; |
1105 | 1109 | count = retval; |
... | ... | @@ -1107,7 +1111,6 @@ |
1107 | 1111 | if (!max) |
1108 | 1112 | max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); |
1109 | 1113 | |
1110 | - pos = *ppos; | |
1111 | 1114 | if (unlikely(pos + count > max)) { |
1112 | 1115 | retval = -EOVERFLOW; |
1113 | 1116 | if (pos >= max) |
1114 | 1117 | |
1115 | 1118 | |
... | ... | @@ -1126,18 +1129,23 @@ |
1126 | 1129 | if (in.file->f_flags & O_NONBLOCK) |
1127 | 1130 | fl = SPLICE_F_NONBLOCK; |
1128 | 1131 | #endif |
1129 | - retval = do_splice_direct(in.file, ppos, out.file, count, fl); | |
1132 | + retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl); | |
1130 | 1133 | |
1131 | 1134 | if (retval > 0) { |
1132 | 1135 | add_rchar(current, retval); |
1133 | 1136 | add_wchar(current, retval); |
1134 | 1137 | fsnotify_access(in.file); |
1135 | 1138 | fsnotify_modify(out.file); |
1139 | + out.file->f_pos = out_pos; | |
1140 | + if (ppos) | |
1141 | + *ppos = pos; | |
1142 | + else | |
1143 | + in.file->f_pos = pos; | |
1136 | 1144 | } |
1137 | 1145 | |
1138 | 1146 | inc_syscr(current); |
1139 | 1147 | inc_syscw(current); |
1140 | - if (*ppos > max) | |
1148 | + if (pos > max) | |
1141 | 1149 | retval = -EOVERFLOW; |
1142 | 1150 | |
1143 | 1151 | fput_out: |
fs/splice.c
... | ... | @@ -1274,7 +1274,7 @@ |
1274 | 1274 | { |
1275 | 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 | 1278 | sd->flags); |
1279 | 1279 | } |
1280 | 1280 | |
... | ... | @@ -1294,7 +1294,7 @@ |
1294 | 1294 | * |
1295 | 1295 | */ |
1296 | 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 | 1299 | struct splice_desc sd = { |
1300 | 1300 | .len = len, |
... | ... | @@ -1302,6 +1302,7 @@ |
1302 | 1302 | .flags = flags, |
1303 | 1303 | .pos = *ppos, |
1304 | 1304 | .u.file = out, |
1305 | + .opos = opos, | |
1305 | 1306 | }; |
1306 | 1307 | long ret; |
1307 | 1308 | |
... | ... | @@ -1325,7 +1326,7 @@ |
1325 | 1326 | { |
1326 | 1327 | struct pipe_inode_info *ipipe; |
1327 | 1328 | struct pipe_inode_info *opipe; |
1328 | - loff_t offset, *off; | |
1329 | + loff_t offset; | |
1329 | 1330 | long ret; |
1330 | 1331 | |
1331 | 1332 | ipipe = get_pipe_info(in); |
1332 | 1333 | |
1333 | 1334 | |
... | ... | @@ -1356,13 +1357,15 @@ |
1356 | 1357 | return -EINVAL; |
1357 | 1358 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) |
1358 | 1359 | return -EFAULT; |
1359 | - off = &offset; | |
1360 | - } else | |
1361 | - off = &out->f_pos; | |
1360 | + } else { | |
1361 | + offset = 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 | 1369 | ret = -EFAULT; |
1367 | 1370 | |
1368 | 1371 | return ret; |
1369 | 1372 | |
1370 | 1373 | |
... | ... | @@ -1376,13 +1379,15 @@ |
1376 | 1379 | return -EINVAL; |
1377 | 1380 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) |
1378 | 1381 | return -EFAULT; |
1379 | - off = &offset; | |
1380 | - } else | |
1381 | - off = &in->f_pos; | |
1382 | + } else { | |
1383 | + offset = 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 | 1391 | ret = -EFAULT; |
1387 | 1392 | |
1388 | 1393 | return ret; |
include/linux/fs.h
... | ... | @@ -2414,8 +2414,6 @@ |
2414 | 2414 | struct file *, loff_t *, size_t, unsigned int); |
2415 | 2415 | extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, |
2416 | 2416 | struct file *out, loff_t *, size_t len, unsigned int flags); |
2417 | -extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |
2418 | - size_t len, unsigned int flags); | |
2419 | 2417 | |
2420 | 2418 | extern void |
2421 | 2419 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); |
include/linux/splice.h