[XFS] Provide XFS support for the splice syscall.

Signed-off-by: Nathan Scott <nathans@sgi.com>
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 85997b1..ae4c475 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -69,7 +69,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_read(
 	struct kiocb		*iocb,
@@ -90,7 +89,6 @@
 	return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_write(
 	struct kiocb	*iocb,
@@ -113,7 +111,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_write(
 	struct kiocb		*iocb,
@@ -134,7 +131,6 @@
 	return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_readv(
 	struct file		*file,
@@ -179,7 +175,6 @@
 	return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_writev(
 	struct file		*file,
@@ -204,7 +199,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_writev(
 	struct file		*file,
@@ -228,7 +222,7 @@
 STATIC ssize_t
 xfs_file_sendfile(
 	struct file		*filp,
-	loff_t			*ppos,
+	loff_t			*pos,
 	size_t			count,
 	read_actor_t		actor,
 	void			*target)
@@ -236,10 +230,80 @@
 	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
 	ssize_t			rval;
 
-	VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
+	VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
 	return rval;
 }
 
+STATIC ssize_t
+xfs_file_sendfile_invis(
+	struct file		*filp,
+	loff_t			*pos,
+	size_t			count,
+	read_actor_t		actor,
+	void			*target)
+{
+	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read(
+	struct file		*infilp,
+	struct inode		*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read_invis(
+	struct file		*infilp,
+	struct inode		*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write(
+	struct inode		*pipe,
+	struct file		*outfilp,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write_invis(
+	struct inode		*pipe,
+	struct file		*outfilp,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
 
 STATIC int
 xfs_file_open(
@@ -251,13 +315,10 @@
 
 	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EFBIG;
-
-	ASSERT(vp);
 	VOP_OPEN(vp, NULL, error);
 	return -error;
 }
 
-
 STATIC int
 xfs_file_release(
 	struct inode	*inode,
@@ -271,7 +332,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_fsync(
 	struct file	*filp,
@@ -285,21 +345,11 @@
 
 	if (datasync)
 		flags |= FSYNC_DATA;
-
-	ASSERT(vp);
 	VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
 	return -error;
 }
 
-/*
- * xfs_file_readdir maps to VOP_READDIR().
- * We need to build a uio, cred, ...
- */
-
-#define nextdp(dp)      ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
-
 #ifdef CONFIG_XFS_DMAPI
-
 STATIC struct page *
 xfs_vm_nopage(
 	struct vm_area_struct	*area,
@@ -319,10 +369,8 @@
 
 	return filemap_nopage(area, address, type);
 }
-
 #endif /* CONFIG_XFS_DMAPI */
 
-
 STATIC int
 xfs_file_readdir(
 	struct file	*filp,
@@ -330,7 +378,7 @@
 	filldir_t	filldir)
 {
 	int		error = 0;
-	vnode_t		*vp;
+	vnode_t		*vp = vn_from_inode(filp->f_dentry->d_inode);
 	uio_t		uio;
 	iovec_t		iov;
 	int		eof = 0;
@@ -340,9 +388,6 @@
 	xfs_off_t	start_offset, curr_offset;
 	xfs_dirent_t	*dbp = NULL;
 
-	vp = vn_from_inode(filp->f_dentry->d_inode);
-	ASSERT(vp);
-
 	/* Try fairly hard to get memory */
 	do {
 		if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
@@ -387,7 +432,7 @@
 			}
 			size -= dbp->d_reclen;
 			curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
-			dbp = nextdp(dbp);
+			dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
 		}
 	}
 done:
@@ -402,7 +447,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_mmap(
 	struct file	*filp,
@@ -457,11 +501,10 @@
 	unsigned int	cmd,
 	unsigned long	arg)
 {
-	int		error;
 	struct inode	*inode = filp->f_dentry->d_inode;
 	vnode_t		*vp = vn_from_inode(inode);
+	int		error;
 
-	ASSERT(vp);
 	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 
@@ -537,6 +580,8 @@
 	.aio_read	= xfs_file_aio_read,
 	.aio_write	= xfs_file_aio_write,
 	.sendfile	= xfs_file_sendfile,
+	.splice_read	= xfs_file_splice_read,
+	.splice_write	= xfs_file_splice_write,
 	.unlocked_ioctl	= xfs_file_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_ioctl,
@@ -558,7 +603,9 @@
 	.writev		= xfs_file_writev_invis,
 	.aio_read	= xfs_file_aio_read_invis,
 	.aio_write	= xfs_file_aio_write_invis,
-	.sendfile	= xfs_file_sendfile,
+	.sendfile	= xfs_file_sendfile_invis,
+	.splice_read	= xfs_file_splice_read_invis,
+	.splice_write	= xfs_file_splice_write_invis,
 	.unlocked_ioctl	= xfs_file_ioctl_invis,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_invis_ioctl,