diff options
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 16 |
1 files changed, 14 insertions, 2 deletions
@@ -382,7 +382,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, | |||
382 | error = ops->confirm(pipe, buf); | 382 | error = ops->confirm(pipe, buf); |
383 | if (error) { | 383 | if (error) { |
384 | if (!ret) | 384 | if (!ret) |
385 | error = ret; | 385 | ret = error; |
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | 388 | ||
@@ -1197,12 +1197,24 @@ int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, | |||
1197 | return ret; | 1197 | return ret; |
1198 | } | 1198 | } |
1199 | 1199 | ||
1200 | /* | ||
1201 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | ||
1202 | * location, so checking ->i_pipe is not enough to verify that this is a | ||
1203 | * pipe. | ||
1204 | */ | ||
1205 | struct pipe_inode_info *get_pipe_info(struct file *file) | ||
1206 | { | ||
1207 | struct inode *i = file->f_path.dentry->d_inode; | ||
1208 | |||
1209 | return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; | ||
1210 | } | ||
1211 | |||
1200 | long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) | 1212 | long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) |
1201 | { | 1213 | { |
1202 | struct pipe_inode_info *pipe; | 1214 | struct pipe_inode_info *pipe; |
1203 | long ret; | 1215 | long ret; |
1204 | 1216 | ||
1205 | pipe = file->f_path.dentry->d_inode->i_pipe; | 1217 | pipe = get_pipe_info(file); |
1206 | if (!pipe) | 1218 | if (!pipe) |
1207 | return -EBADF; | 1219 | return -EBADF; |
1208 | 1220 | ||