diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-25 17:24:12 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-25 17:24:12 -0400 |
commit | a9e5f4d0780ec9cda7a70b08294d7718431b62a1 (patch) | |
tree | f21fa310b6ea63f49cf6d710fcd84fe8d66282f3 /fs/gfs2/ops_address.c | |
parent | 52f341cf75d2da84811127582616984eb0602360 (diff) |
[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.c | 54 |
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) | |||
589 | return; | 589 | return; |
590 | } | 590 | } |
591 | 591 | ||
592 | static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov, | 592 | static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, |
593 | loff_t offset, unsigned long nr_segs) | 593 | const struct iovec *iov, loff_t offset, |
594 | unsigned long nr_segs) | ||
594 | { | 595 | { |
595 | struct file *file = iocb->ki_filp; | 596 | struct file *file = iocb->ki_filp; |
596 | struct inode *inode = file->f_mapping->host; | 597 | 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, | |||
598 | struct gfs2_holder gh; | 599 | struct gfs2_holder gh; |
599 | int rv; | 600 | int rv; |
600 | 601 | ||
602 | if (rw == READ) | ||
603 | mutex_lock(&inode->i_mutex); | ||
601 | /* | 604 | /* |
602 | * Shared lock, even though its write, since we do no allocation | 605 | * Shared lock, even if its a write, since we do no allocation |
603 | * on this path. All we need change is atime. | 606 | * on this path. All we need change is atime. |
604 | */ | 607 | */ |
605 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); | 608 | 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, | |||
607 | if (rv) | 610 | if (rv) |
608 | goto out; | 611 | goto out; |
609 | 612 | ||
613 | if (offset > i_size_read(inode)) | ||
614 | goto out; | ||
615 | |||
610 | /* | 616 | /* |
611 | * Should we return an error here? I can't see that O_DIRECT for | 617 | * Should we return an error here? I can't see that O_DIRECT for |
612 | * a journaled file makes any sense. For now we'll silently fall | 618 | * 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, | |||
619 | if (gfs2_is_stuffed(ip)) | 625 | if (gfs2_is_stuffed(ip)) |
620 | goto out; | 626 | goto out; |
621 | 627 | ||
622 | rv = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev, | 628 | rv = blockdev_direct_IO_own_locking(rw, iocb, inode, |
623 | iov, offset, nr_segs, gfs2_get_block, | 629 | inode->i_sb->s_bdev, |
624 | NULL, DIO_OWN_LOCKING); | 630 | iov, offset, nr_segs, |
631 | gfs2_get_block, NULL); | ||
625 | out: | 632 | out: |
626 | gfs2_glock_dq_m(1, &gh); | 633 | gfs2_glock_dq_m(1, &gh); |
627 | gfs2_holder_uninit(&gh); | 634 | gfs2_holder_uninit(&gh); |
635 | if (rw == READ) | ||
636 | mutex_unlock(&inode->i_mutex); | ||
628 | 637 | ||
629 | return rv; | 638 | return rv; |
630 | } | 639 | } |
631 | 640 | ||
632 | /** | 641 | /** |
633 | * gfs2_direct_IO | ||
634 | * | ||
635 | * This is called with a shared lock already held for the read path. | ||
636 | * Currently, no locks are held when the write path is called. | ||
637 | */ | ||
638 | static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | ||
639 | const struct iovec *iov, loff_t offset, | ||
640 | unsigned long nr_segs) | ||
641 | { | ||
642 | struct file *file = iocb->ki_filp; | ||
643 | struct inode *inode = file->f_mapping->host; | ||
644 | struct gfs2_inode *ip = GFS2_I(inode); | ||
645 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
646 | int ret; | ||
647 | |||
648 | if (rw == WRITE) | ||
649 | return gfs2_direct_IO_write(iocb, iov, offset, nr_segs); | ||
650 | |||
651 | if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)) || | ||
652 | gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) | ||
653 | return -EINVAL; | ||
654 | |||
655 | mutex_lock(&inode->i_mutex); | ||
656 | ret = __blockdev_direct_IO(READ, iocb, inode, inode->i_sb->s_bdev, iov, | ||
657 | offset, nr_segs, gfs2_get_block, NULL, | ||
658 | DIO_OWN_LOCKING); | ||
659 | mutex_unlock(&inode->i_mutex); | ||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * stuck_releasepage - We're stuck in gfs2_releasepage(). Print stuff out. | 642 | * stuck_releasepage - We're stuck in gfs2_releasepage(). Print stuff out. |
665 | * @bh: the buffer we're stuck on | 643 | * @bh: the buffer we're stuck on |
666 | * | 644 | * |
@@ -765,7 +743,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
765 | } | 743 | } |
766 | while (bh != head); | 744 | while (bh != head); |
767 | 745 | ||
768 | out: | 746 | out: |
769 | return try_to_free_buffers(page); | 747 | return try_to_free_buffers(page); |
770 | } | 748 | } |
771 | 749 | ||