Commit 7995bd287134f6c8f80d94bebe7396f05a9bc42b

Authored by Al Viro
1 parent c9036e9f3b

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

... ... @@ -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;
... ... @@ -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:
... ... @@ -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;
... ... @@ -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
... ... @@ -35,6 +35,7 @@
35 35 void *data; /* cookie */
36 36 } u;
37 37 loff_t pos; /* file position */
  38 + loff_t *opos; /* sendfile: output position */
38 39 size_t num_spliced; /* number of bytes already spliced */
39 40 bool need_wakeup; /* need to wake up writer */
40 41 };