summaryrefslogtreecommitdiff
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-07-25 17:24:12 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-07-25 17:24:12 -0400
commita9e5f4d0780ec9cda7a70b08294d7718431b62a1 (patch)
treef21fa310b6ea63f49cf6d710fcd84fe8d66282f3 /fs/gfs2/ops_address.c
parent52f341cf75d2da84811127582616984eb0602360 (diff)
downloadlwn-a9e5f4d0780ec9cda7a70b08294d7718431b62a1.tar.gz
lwn-a9e5f4d0780ec9cda7a70b08294d7718431b62a1.zip
[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>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c54
1 files changed, 16 insertions, 38 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 031270ad55e2..d33f6aa79731 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -589,8 +589,9 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset)
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 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
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 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
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 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
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 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
}
while (bh != head);
- out:
+out:
return try_to_free_buffers(page);
}