Messages in this thread Patch in this message |  | | | Date | Thu, 6 May 2004 15:19:00 +0200 | | From | Jörn Engel <> | | Subject | [PATCH COW] sendfile |
| |
Patch 2
Jörn
-- Simplicity is prerequisite for reliability. -- Edsger W. Dijkstra
Creates vfs_sendfile(), which can be called from other places within the kernel. Such other places include copyfile() and cowlinks.
In principle, this just removes code from do_sendfile() to vfs_sendfile(). On top of that, it adds a check to out_inode, identical to the one on in_inode. True, the check for out_inode was never needed, maybe that tells you something about the check to in_inode as well. ;)
fs/read_write.c | 99 +++++++++++++++++++++++++++-------------------- include/linux/fs.h | 1 include/linux/syscalls.h | 2 3 files changed, 60 insertions(+), 42 deletions(-) --- linux-2.6.5cow/fs/read_write.c~copyfile 2004-04-06 18:50:59.000000000 +0200 +++ linux-2.6.5cow/fs/read_write.c 2004-04-25 03:21:41.000000000 +0200 @@ -537,12 +537,66 @@ return ret; } +ssize_t vfs_sendfile(struct file *out_file, struct file *in_file, loff_t *ppos, + size_t count, loff_t max) +{ + struct inode * in_inode, * out_inode; + loff_t pos; + ssize_t ret; + + /* verify in_file */ + in_inode = in_file->f_dentry->d_inode; + if (!in_inode) + return -EINVAL; + if (!in_file->f_op || !in_file->f_op->sendfile) + return -EINVAL; + + if (!ppos) + ppos = &in_file->f_pos; + ret = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, *ppos, count); + if (ret) + return ret; + + /* verify out_file */ + out_inode = out_file->f_dentry->d_inode; + if (!out_inode) + return -EINVAL; + if (!out_file->f_op || !out_file->f_op->sendpage) + return -EINVAL; + + ret = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count); + if (ret) + return ret; + + ret = security_file_permission (out_file, MAY_WRITE); + if (ret) + return ret; + + if (!max) + max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); + + pos = *ppos; + if (unlikely(pos < 0)) + return -EINVAL; + if (unlikely(pos + count > max)) { + if (pos >= max) + return -EOVERFLOW; + count = max - pos; + } + + ret = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); + + if (*ppos > max) + return -EOVERFLOW; + return ret; +} + +EXPORT_SYMBOL(vfs_sendfile); + static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count, loff_t max) { struct file * in_file, * out_file; - struct inode * in_inode, * out_inode; - loff_t pos; ssize_t retval; int fput_needed_in, fput_needed_out; @@ -555,17 +609,6 @@ goto out; if (!(in_file->f_mode & FMODE_READ)) goto fput_in; - retval = -EINVAL; - in_inode = in_file->f_dentry->d_inode; - if (!in_inode) - goto fput_in; - if (!in_file->f_op || !in_file->f_op->sendfile) - goto fput_in; - if (!ppos) - ppos = &in_file->f_pos; - retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, *ppos, count); - if (retval) - goto fput_in; retval = security_file_permission (in_file, MAY_READ); if (retval) @@ -580,36 +623,8 @@ goto fput_in; if (!(out_file->f_mode & FMODE_WRITE)) goto fput_out; - retval = -EINVAL; - if (!out_file->f_op || !out_file->f_op->sendpage) - goto fput_out; - out_inode = out_file->f_dentry->d_inode; - retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count); - if (retval) - goto fput_out; - - retval = security_file_permission (out_file, MAY_WRITE); - if (retval) - goto fput_out; - - if (!max) - max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); - - pos = *ppos; - retval = -EINVAL; - if (unlikely(pos < 0)) - goto fput_out; - if (unlikely(pos + count > max)) { - retval = -EOVERFLOW; - if (pos >= max) - goto fput_out; - count = max - pos; - } - - retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); - if (*ppos > max) - retval = -EOVERFLOW; + retval = vfs_sendfile(out_file, in_file, ppos, count, max); fput_out: fput_light(out_file, fput_needed_out); --- linux-2.6.5cow/include/linux/fs.h~copyfile 2004-04-20 16:20:21.000000000 +0200 +++ linux-2.6.5cow/include/linux/fs.h 2004-04-27 16:34:23.000000000 +0200 @@ -877,6 +877,7 @@ unsigned long, loff_t *); extern ssize_t vfs_writev(struct file *, const struct iovec __user *, unsigned long, loff_t *); +ssize_t vfs_sendfile(struct file *, struct file *, loff_t *, size_t, loff_t); /* * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called --- linux-2.6.5cow/include/linux/syscalls.h~copyfile 2004-04-14 16:22:15.000000000 +0200 +++ linux-2.6.5cow/include/linux/syscalls.h 2004-04-27 16:34:23.000000000 +0200 @@ -278,6 +278,8 @@ asmlinkage long sys_unlink(const char __user *pathname); asmlinkage long sys_rename(const char __user *oldname, const char __user *newname); +asmlinkage long sys_copyfile(const char __user *from, const char __user *to, + umode_t mode); asmlinkage long sys_chmod(const char __user *filename, mode_t mode); asmlinkage long sys_fchmod(unsigned int fd, mode_t mode); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |