diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 12:10:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 12:10:19 -0400 |
commit | 790eac5640abf7a57fa3a644386df330e18c11b0 (patch) | |
tree | 08de20bde44f59e51b91ff473a71047c2957e8c9 /fs/splice.c | |
parent | 0b0585c3e192967cb2ef0ac0816eb8a8c8d99840 (diff) | |
parent | 48bde8d3620f5f3c6ae9ff599eb404055ae51664 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second set of VFS changes from Al Viro:
"Assorted f_pos race fixes, making do_splice_direct() safe to call with
i_mutex on parent, O_TMPFILE support, Jeff's locks.c series,
->d_hash/->d_compare calling conventions changes from Linus, misc
stuff all over the place."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits)
Document ->tmpfile()
ext4: ->tmpfile() support
vfs: export lseek_execute() to modules
lseek_execute() doesn't need an inode passed to it
block_dev: switch to fixed_size_llseek()
cpqphp_sysfs: switch to fixed_size_llseek()
tile-srom: switch to fixed_size_llseek()
proc_powerpc: switch to fixed_size_llseek()
ubi/cdev: switch to fixed_size_llseek()
pci/proc: switch to fixed_size_llseek()
isapnp: switch to fixed_size_llseek()
lpfc: switch to fixed_size_llseek()
locks: give the blocked_hash its own spinlock
locks: add a new "lm_owner_key" lock operation
locks: turn the blocked_list into a hashtable
locks: convert fl_link to a hlist_node
locks: avoid taking global lock if possible when waking up blocked waiters
locks: protect most of the file_lock handling with i_lock
locks: encapsulate the fl_link list handling
locks: make "added" in __posix_lock_file a bool
...
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/fs/splice.c b/fs/splice.c index d37431dd60a1..3b7ee656f3aa 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -1098,27 +1098,13 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
1098 | { | 1098 | { |
1099 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, | 1099 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, |
1100 | loff_t *, size_t, unsigned int); | 1100 | loff_t *, size_t, unsigned int); |
1101 | int ret; | ||
1102 | |||
1103 | if (unlikely(!(out->f_mode & FMODE_WRITE))) | ||
1104 | return -EBADF; | ||
1105 | |||
1106 | if (unlikely(out->f_flags & O_APPEND)) | ||
1107 | return -EINVAL; | ||
1108 | |||
1109 | ret = rw_verify_area(WRITE, out, ppos, len); | ||
1110 | if (unlikely(ret < 0)) | ||
1111 | return ret; | ||
1112 | 1101 | ||
1113 | if (out->f_op && out->f_op->splice_write) | 1102 | if (out->f_op && out->f_op->splice_write) |
1114 | splice_write = out->f_op->splice_write; | 1103 | splice_write = out->f_op->splice_write; |
1115 | else | 1104 | else |
1116 | splice_write = default_file_splice_write; | 1105 | splice_write = default_file_splice_write; |
1117 | 1106 | ||
1118 | file_start_write(out); | 1107 | return splice_write(pipe, out, ppos, len, flags); |
1119 | ret = splice_write(pipe, out, ppos, len, flags); | ||
1120 | file_end_write(out); | ||
1121 | return ret; | ||
1122 | } | 1108 | } |
1123 | 1109 | ||
1124 | /* | 1110 | /* |
@@ -1307,6 +1293,16 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
1307 | }; | 1293 | }; |
1308 | long ret; | 1294 | long ret; |
1309 | 1295 | ||
1296 | if (unlikely(!(out->f_mode & FMODE_WRITE))) | ||
1297 | return -EBADF; | ||
1298 | |||
1299 | if (unlikely(out->f_flags & O_APPEND)) | ||
1300 | return -EINVAL; | ||
1301 | |||
1302 | ret = rw_verify_area(WRITE, out, opos, len); | ||
1303 | if (unlikely(ret < 0)) | ||
1304 | return ret; | ||
1305 | |||
1310 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | 1306 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); |
1311 | if (ret > 0) | 1307 | if (ret > 0) |
1312 | *ppos = sd.pos; | 1308 | *ppos = sd.pos; |
@@ -1362,7 +1358,19 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1362 | offset = out->f_pos; | 1358 | offset = out->f_pos; |
1363 | } | 1359 | } |
1364 | 1360 | ||
1361 | if (unlikely(!(out->f_mode & FMODE_WRITE))) | ||
1362 | return -EBADF; | ||
1363 | |||
1364 | if (unlikely(out->f_flags & O_APPEND)) | ||
1365 | return -EINVAL; | ||
1366 | |||
1367 | ret = rw_verify_area(WRITE, out, &offset, len); | ||
1368 | if (unlikely(ret < 0)) | ||
1369 | return ret; | ||
1370 | |||
1371 | file_start_write(out); | ||
1365 | ret = do_splice_from(ipipe, out, &offset, len, flags); | 1372 | ret = do_splice_from(ipipe, out, &offset, len, flags); |
1373 | file_end_write(out); | ||
1366 | 1374 | ||
1367 | if (!off_out) | 1375 | if (!off_out) |
1368 | out->f_pos = offset; | 1376 | out->f_pos = offset; |