[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);
}