aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2006-11-04 06:49:32 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-11-04 11:45:39 -0500
commitddac0d39cf437d02fde9795ae57d9c4b4c146de9 (patch)
tree36766a2ff9e4872f06d9c4e4b269758647aa3cf6 /fs/splice.c
parentaaa9b971398f62ab97c1da4f7c352667eb3452c9 (diff)
[PATCH] splice: fix problem introduced with inode diet
After the inode slimming patch that unionised i_pipe/i_bdev/i_cdev, it's no longer enough to check for existance of ->i_pipe to verify that this is a pipe. Original patch from Eric Dumazet <dada1@cosmosbay.com> Final solution suggested by Linus. Signed-off-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 8d705954d294..da74583a00ee 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1109,6 +1109,19 @@ out_release:
1109EXPORT_SYMBOL(do_splice_direct); 1109EXPORT_SYMBOL(do_splice_direct);
1110 1110
1111/* 1111/*
1112 * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
1113 * location, so checking ->i_pipe is not enough to verify that this is a
1114 * pipe.
1115 */
1116static inline struct pipe_inode_info *pipe_info(struct inode *inode)
1117{
1118 if (S_ISFIFO(inode->i_mode))
1119 return inode->i_pipe;
1120
1121 return NULL;
1122}
1123
1124/*
1112 * Determine where to splice to/from. 1125 * Determine where to splice to/from.
1113 */ 1126 */
1114static long do_splice(struct file *in, loff_t __user *off_in, 1127static long do_splice(struct file *in, loff_t __user *off_in,
@@ -1119,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1119 loff_t offset, *off; 1132 loff_t offset, *off;
1120 long ret; 1133 long ret;
1121 1134
1122 pipe = in->f_dentry->d_inode->i_pipe; 1135 pipe = pipe_info(in->f_dentry->d_inode);
1123 if (pipe) { 1136 if (pipe) {
1124 if (off_in) 1137 if (off_in)
1125 return -ESPIPE; 1138 return -ESPIPE;
@@ -1140,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1140 return ret; 1153 return ret;
1141 } 1154 }
1142 1155
1143 pipe = out->f_dentry->d_inode->i_pipe; 1156 pipe = pipe_info(out->f_dentry->d_inode);
1144 if (pipe) { 1157 if (pipe) {
1145 if (off_out) 1158 if (off_out)
1146 return -ESPIPE; 1159 return -ESPIPE;
@@ -1298,7 +1311,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
1298static long do_vmsplice(struct file *file, const struct iovec __user *iov, 1311static long do_vmsplice(struct file *file, const struct iovec __user *iov,
1299 unsigned long nr_segs, unsigned int flags) 1312 unsigned long nr_segs, unsigned int flags)
1300{ 1313{
1301 struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe; 1314 struct pipe_inode_info *pipe;
1302 struct page *pages[PIPE_BUFFERS]; 1315 struct page *pages[PIPE_BUFFERS];
1303 struct partial_page partial[PIPE_BUFFERS]; 1316 struct partial_page partial[PIPE_BUFFERS];
1304 struct splice_pipe_desc spd = { 1317 struct splice_pipe_desc spd = {
@@ -1308,7 +1321,8 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
1308 .ops = &user_page_pipe_buf_ops, 1321 .ops = &user_page_pipe_buf_ops,
1309 }; 1322 };
1310 1323
1311 if (unlikely(!pipe)) 1324 pipe = pipe_info(file->f_dentry->d_inode);
1325 if (!pipe)
1312 return -EBADF; 1326 return -EBADF;
1313 if (unlikely(nr_segs > UIO_MAXIOV)) 1327 if (unlikely(nr_segs > UIO_MAXIOV))
1314 return -EINVAL; 1328 return -EINVAL;
@@ -1535,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
1535static long do_tee(struct file *in, struct file *out, size_t len, 1549static long do_tee(struct file *in, struct file *out, size_t len,
1536 unsigned int flags) 1550 unsigned int flags)
1537{ 1551{
1538 struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe; 1552 struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
1539 struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe; 1553 struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
1540 int ret = -EINVAL; 1554 int ret = -EINVAL;
1541 1555
1542 /* 1556 /*