[GFS2] Alter direct I/O path

As per comments received, alter the GFS2 direct I/O path so that
it uses the standard read functions "out of the box". Needs a
small change to one of the VFS functions. This reduces the size
of the code quite a lot and also removes the need for one new export.

Some more work remains to be done, but this is the bones of the
thing.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 031270a..d33f6aa 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -589,8 +589,9 @@
 	return;
 }
 
-static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
-				    loff_t offset, unsigned long nr_segs)
+static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
+			      const struct iovec *iov, loff_t offset,
+			      unsigned long nr_segs)
 {
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_mapping->host;
@@ -598,8 +599,10 @@
 	struct gfs2_holder gh;
 	int rv;
 
+	if (rw == READ)
+		mutex_lock(&inode->i_mutex);
 	/*
-	 * Shared lock, even though its write, since we do no allocation
+	 * Shared lock, even if its a write, since we do no allocation
 	 * on this path. All we need change is atime.
 	 */
 	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
@@ -607,6 +610,9 @@
 	if (rv)
 		goto out;
 
+	if (offset > i_size_read(inode))
+		goto out;
+
 	/*
 	 * Should we return an error here? I can't see that O_DIRECT for
 	 * a journaled file makes any sense. For now we'll silently fall
@@ -619,48 +625,20 @@
 	if (gfs2_is_stuffed(ip))
 		goto out;
 
-	rv = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev,
-				  iov, offset, nr_segs, gfs2_get_block,
-				  NULL, DIO_OWN_LOCKING);
+	rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
+					    inode->i_sb->s_bdev,
+					    iov, offset, nr_segs,
+					    gfs2_get_block, NULL);
 out:
 	gfs2_glock_dq_m(1, &gh);
 	gfs2_holder_uninit(&gh);
+	if (rw == READ)
+		mutex_unlock(&inode->i_mutex);
 
 	return rv;
 }
 
 /**
- * gfs2_direct_IO
- *
- * This is called with a shared lock already held for the read path.
- * Currently, no locks are held when the write path is called.
- */
-static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
-			      const struct iovec *iov, loff_t offset,
-			      unsigned long nr_segs)
-{
-	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_mapping->host;
-	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_sbd *sdp = GFS2_SB(inode);
-	int ret;
-
-	if (rw == WRITE)
-		return gfs2_direct_IO_write(iocb, iov, offset, nr_segs);
-
-	if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)) ||
-	    gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
-		return -EINVAL;
-
-	mutex_lock(&inode->i_mutex);
-	ret = __blockdev_direct_IO(READ, iocb, inode, inode->i_sb->s_bdev, iov,
-			 	   offset, nr_segs, gfs2_get_block, NULL,
-				   DIO_OWN_LOCKING);
-	mutex_unlock(&inode->i_mutex);
-	return ret;
-}
-
-/**
  * stuck_releasepage - We're stuck in gfs2_releasepage().  Print stuff out.
  * @bh: the buffer we're stuck on
  *
@@ -765,7 +743,7 @@
 	}
 	while (bh != head);
 
- out:
+out:
 	return try_to_free_buffers(page);
 }