diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/ext2/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/ext2/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/ext2/file.c 2007-08-05 20:53:12 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/ext2/file.c 2007-09-12 05:54:10 +0200 @@ -54,7 +54,6 @@ const struct file_operations ext2_file_o .release = ext2_release_file, .fsync = ext2_sync_file, .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, }; diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/ext3/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/ext3/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/ext3/file.c 2007-08-05 20:53:12 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/ext3/file.c 2007-09-12 05:54:10 +0200 @@ -121,7 +121,6 @@ const struct file_operations ext3_file_o .release = ext3_release_file, .fsync = ext3_sync_file, .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, }; diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/ext4/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/ext4/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/ext4/file.c 2007-08-05 20:53:12 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/ext4/file.c 2007-09-12 05:54:10 +0200 @@ -121,7 +121,6 @@ const struct file_operations ext4_file_o .release = ext4_release_file, .fsync = ext4_sync_file, .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, }; diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/jffs2/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/jffs2/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/jffs2/file.c 2007-08-19 17:16:32 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/jffs2/file.c 2007-09-12 05:54:10 +0200 @@ -51,8 +51,7 @@ const struct file_operations jffs2_file_ .ioctl = jffs2_ioctl, .mmap = generic_file_readonly_mmap, .fsync = jffs2_fsync, - .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, + .sendfile = generic_file_sendfile }; /* jffs2_file_inode_operations */ diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/jfs/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/jfs/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/jfs/file.c 2007-08-05 20:53:12 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/jfs/file.c 2007-09-12 05:54:10 +0200 @@ -110,7 +110,6 @@ const struct file_operations jfs_file_op .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, .fsync = jfs_fsync, diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/namei.c linux-2.6.22.6-vs2.3.0.20.1/fs/namei.c --- linux-2.6.22.6-vs2.3.0.20/fs/namei.c 2007-09-05 02:43:35 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/namei.c 2007-09-12 08:08:10 +0200 @@ -2759,7 +2759,7 @@ struct dentry *cow_break_link(const char struct file *old_file; struct file *new_file; char *to, *path, pad='\251'; - loff_t size; + loff_t ppos, size; vxdprintk(VXD_CBIT(misc, 1), "cow_break_link(»%s«)", pathname); path = kmalloc(PATH_MAX, GFP_KERNEL); @@ -2841,8 +2841,9 @@ retry: } size = i_size_read(old_file->f_dentry->d_inode); - ret = vfs_sendfile(new_file, old_file, NULL, size, 0); - vxdprintk(VXD_CBIT(misc, 2), "vfs_sendfile: %d", ret); + ppos = 0; + ret = do_splice_direct(old_file, &ppos, new_file, size, 0); + vxdprintk(VXD_CBIT(misc, 2), "do_splice_direct: %d", ret); if (ret < 0) { res = ERR_PTR(ret); goto out_fput_both; diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/read_write.c linux-2.6.22.6-vs2.3.0.20.1/fs/read_write.c --- linux-2.6.22.6-vs2.3.0.20/fs/read_write.c 2007-08-05 20:53:13 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/read_write.c 2007-09-12 05:54:21 +0200 @@ -701,77 +701,12 @@ sys_writev(unsigned long fd, const struc 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_path.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; - else - if (!(in_file->f_mode & FMODE_PREAD)) - return -ESPIPE; - - ret = rw_verify_area(READ, in_file, ppos, count); - if (ret < 0) - return ret; - count = ret; - - /* verify out_file */ - out_inode = out_file->f_path.dentry->d_inode; - if (!out_inode) - return -EINVAL; - if (!out_file->f_op || !out_file->f_op->sendpage) - return -EINVAL; - - ret = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); - if (ret < 0) - return ret; - count = 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 (ret > 0) { - add_rchar(current, ret); - add_wchar(current, ret); - } - - 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; @@ -784,6 +719,22 @@ static ssize_t do_sendfile(int out_fd, i goto out; if (!(in_file->f_mode & FMODE_READ)) goto fput_in; + retval = -EINVAL; + in_inode = in_file->f_path.dentry->d_inode; + if (!in_inode) + goto fput_in; + if (!in_file->f_op || !in_file->f_op->sendfile) + goto fput_in; + retval = -ESPIPE; + if (!ppos) + ppos = &in_file->f_pos; + else + if (!(in_file->f_mode & FMODE_PREAD)) + goto fput_in; + retval = rw_verify_area(READ, in_file, ppos, count); + if (retval < 0) + goto fput_in; + count = retval; retval = security_file_permission (in_file, MAY_READ); if (retval) @@ -798,11 +749,45 @@ static ssize_t do_sendfile(int out_fd, i 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_path.dentry->d_inode; + retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); + if (retval < 0) + goto fput_out; + count = retval; - retval = vfs_sendfile(out_file, in_file, ppos, count, max); + 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 (retval > 0) { + add_rchar(current, retval); + add_wchar(current, retval); + } inc_syscr(current); inc_syscw(current); + if (*ppos > max) + retval = -EOVERFLOW; + fput_out: fput_light(out_file, fput_needed_out); fput_in: diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/reiserfs/file.c linux-2.6.22.6-vs2.3.0.20.1/fs/reiserfs/file.c --- linux-2.6.22.6-vs2.3.0.20/fs/reiserfs/file.c 2007-08-05 20:53:13 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/reiserfs/file.c 2007-09-12 05:54:10 +0200 @@ -1532,7 +1532,6 @@ const struct file_operations reiserfs_fi .release = reiserfs_file_release, .fsync = reiserfs_sync_file, .sendfile = generic_file_sendfile, - .sendpage = generic_file_sendpage, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, .splice_read = generic_file_splice_read, diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/fs/xfs/linux-2.6/xfs_file.c linux-2.6.22.6-vs2.3.0.20.1/fs/xfs/linux-2.6/xfs_file.c --- linux-2.6.22.6-vs2.3.0.20/fs/xfs/linux-2.6/xfs_file.c 2007-08-05 20:53:13 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/fs/xfs/linux-2.6/xfs_file.c 2007-09-12 05:54:10 +0200 @@ -453,7 +453,6 @@ const struct file_operations xfs_file_op .aio_read = xfs_file_aio_read, .aio_write = xfs_file_aio_write, .sendfile = xfs_file_sendfile, - .sendpage = generic_file_sendpage, .splice_read = xfs_file_splice_read, .splice_write = xfs_file_splice_write, .unlocked_ioctl = xfs_file_ioctl, @@ -477,7 +476,6 @@ const struct file_operations xfs_invis_f .aio_read = xfs_file_aio_read_invis, .aio_write = xfs_file_aio_write_invis, .sendfile = xfs_file_sendfile_invis, - .sendpage = generic_file_sendpage, .splice_read = xfs_file_splice_read_invis, .splice_write = xfs_file_splice_write_invis, .unlocked_ioctl = xfs_file_ioctl_invis, diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/include/linux/fs.h linux-2.6.22.6-vs2.3.0.20.1/include/linux/fs.h --- linux-2.6.22.6-vs2.3.0.20/include/linux/fs.h 2007-08-05 20:53:13 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/include/linux/fs.h 2007-09-12 05:54:10 +0200 @@ -1790,7 +1790,6 @@ extern ssize_t generic_file_buffered_wri extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); -extern ssize_t generic_file_sendpage(struct file *, struct page *, int, size_t, loff_t *, int); extern void do_generic_mapping_read(struct address_space *mapping, struct file_ra_state *, struct file *, loff_t *, read_descriptor_t *, read_actor_t); diff -NurpP --minimal linux-2.6.22.6-vs2.3.0.20/mm/filemap.c linux-2.6.22.6-vs2.3.0.20.1/mm/filemap.c --- linux-2.6.22.6-vs2.3.0.20/mm/filemap.c 2007-08-05 20:53:13 +0200 +++ linux-2.6.22.6-vs2.3.0.20.1/mm/filemap.c 2007-09-12 05:54:10 +0200 @@ -1245,31 +1245,6 @@ int file_send_actor(read_descriptor_t * return written; } -/* FIXME: It would be as simple as this, if we had a (void __user*) to write. - * We already have a kernel buffer, so it should be even simpler, right? ;) - * - * Yes, sorta. After duplicating the complete path of generic_file_write(), - * at least some special cases could be removed, so the copy is simpler than - * the original. But it remains a copy, so overall complexity increases. - */ -static ssize_t -generic_kernel_file_write(struct file *, const char *, size_t, loff_t *); - -ssize_t generic_file_sendpage(struct file *file, struct page *page, - int offset, size_t size, loff_t *ppos, int more) -{ - ssize_t ret; - char *kaddr; - - kaddr = kmap(page); - ret = generic_kernel_file_write(file, kaddr + offset, size, ppos); - kunmap(page); - - return ret; -} - -EXPORT_SYMBOL(generic_file_sendpage); - ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos, size_t count, read_actor_t actor, void *target) {