diff options
author | Dave Chinner <dchinner@redhat.com> | 2011-01-10 18:17:30 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2011-01-10 18:17:30 -0500 |
commit | 637bbc75d9fda57c7bc77ce5ee37e29a77a0520d (patch) | |
tree | 285e82a7afdf7b5e1468f17288e122f7ec269ac7 /fs/xfs/linux-2.6 | |
parent | f0d26e860b6c496464c5c8165d7df08dabde01fa (diff) |
xfs: split buffered IO write path from xfs_file_aio_write
Complete the split of the different write IO paths by splitting the
buffered IO write path out of xfs_file_aio_write(). This makes the
different mechanisms of the write patchs easier to follow.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Alex Elder <aelder@sgi.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 146 |
1 files changed, 69 insertions, 77 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 00661fd21fc0..e2bcf51d292e 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -739,58 +739,31 @@ xfs_file_dio_aio_write( | |||
739 | } | 739 | } |
740 | 740 | ||
741 | STATIC ssize_t | 741 | STATIC ssize_t |
742 | xfs_file_aio_write( | 742 | xfs_file_buffered_aio_write( |
743 | struct kiocb *iocb, | 743 | struct kiocb *iocb, |
744 | const struct iovec *iovp, | 744 | const struct iovec *iovp, |
745 | unsigned long nr_segs, | 745 | unsigned long nr_segs, |
746 | loff_t pos) | 746 | loff_t pos, |
747 | size_t ocount, | ||
748 | int *iolock) | ||
747 | { | 749 | { |
748 | struct file *file = iocb->ki_filp; | 750 | struct file *file = iocb->ki_filp; |
749 | struct address_space *mapping = file->f_mapping; | 751 | struct address_space *mapping = file->f_mapping; |
750 | struct inode *inode = mapping->host; | 752 | struct inode *inode = mapping->host; |
751 | struct xfs_inode *ip = XFS_I(inode); | 753 | struct xfs_inode *ip = XFS_I(inode); |
752 | struct xfs_mount *mp = ip->i_mount; | 754 | ssize_t ret; |
753 | ssize_t ret = 0; | 755 | int enospc = 0; |
754 | int ioflags = 0; | ||
755 | xfs_fsize_t new_size; | 756 | xfs_fsize_t new_size; |
756 | int iolock; | 757 | size_t count = ocount; |
757 | size_t ocount = 0, count; | ||
758 | |||
759 | XFS_STATS_INC(xs_write_calls); | ||
760 | |||
761 | BUG_ON(iocb->ki_pos != pos); | ||
762 | |||
763 | if (unlikely(file->f_flags & O_DIRECT)) | ||
764 | ioflags |= IO_ISDIRECT; | ||
765 | if (file->f_mode & FMODE_NOCMTIME) | ||
766 | ioflags |= IO_INVIS; | ||
767 | |||
768 | ret = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ); | ||
769 | if (ret) | ||
770 | return ret; | ||
771 | |||
772 | count = ocount; | ||
773 | if (count == 0) | ||
774 | return 0; | ||
775 | |||
776 | xfs_wait_for_freeze(mp, SB_FREEZE_WRITE); | ||
777 | |||
778 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
779 | return -EIO; | ||
780 | 758 | ||
781 | relock: | 759 | *iolock = XFS_IOLOCK_EXCL; |
782 | if (ioflags & IO_ISDIRECT) { | 760 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); |
783 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, | ||
784 | ocount, &iolock); | ||
785 | goto done_io; | ||
786 | } | ||
787 | iolock = XFS_IOLOCK_EXCL; | ||
788 | 761 | ||
789 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL|iolock); | ||
790 | ret = generic_write_checks(file, &pos, &count, | 762 | ret = generic_write_checks(file, &pos, &count, |
791 | S_ISBLK(inode->i_mode)); | 763 | S_ISBLK(inode->i_mode)); |
792 | if (ret) { | 764 | if (ret) { |
793 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL|iolock); | 765 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); |
766 | *iolock = 0; | ||
794 | return ret; | 767 | return ret; |
795 | } | 768 | } |
796 | 769 | ||
@@ -798,67 +771,86 @@ relock: | |||
798 | if (new_size > ip->i_size) | 771 | if (new_size > ip->i_size) |
799 | ip->i_new_size = new_size; | 772 | ip->i_new_size = new_size; |
800 | 773 | ||
801 | if (likely(!(ioflags & IO_INVIS))) | 774 | if (likely(!(file->f_mode & FMODE_NOCMTIME))) |
802 | file_update_time(file); | 775 | file_update_time(file); |
803 | 776 | ||
804 | /* | ||
805 | * If the offset is beyond the size of the file, we have a couple | ||
806 | * of things to do. First, if there is already space allocated | ||
807 | * we need to either create holes or zero the disk or ... | ||
808 | * | ||
809 | * If there is a page where the previous size lands, we need | ||
810 | * to zero it out up to the new size. | ||
811 | */ | ||
812 | |||
813 | if (pos > ip->i_size) { | 777 | if (pos > ip->i_size) { |
814 | ret = -xfs_zero_eof(ip, pos, ip->i_size); | 778 | ret = -xfs_zero_eof(ip, pos, ip->i_size); |
815 | if (ret) { | 779 | if (ret) { |
816 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | 780 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); |
817 | goto out_unlock_internal; | 781 | return ret; |
818 | } | 782 | } |
819 | } | 783 | } |
820 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | 784 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); |
821 | 785 | ||
822 | /* | ||
823 | * If we're writing the file then make sure to clear the | ||
824 | * setuid and setgid bits if the process is not being run | ||
825 | * by root. This keeps people from modifying setuid and | ||
826 | * setgid binaries. | ||
827 | */ | ||
828 | ret = file_remove_suid(file); | 786 | ret = file_remove_suid(file); |
829 | if (unlikely(ret)) | 787 | if (unlikely(ret)) |
830 | goto out_unlock_internal; | 788 | return ret; |
831 | 789 | ||
832 | /* We can write back this queue in page reclaim */ | 790 | /* We can write back this queue in page reclaim */ |
833 | current->backing_dev_info = mapping->backing_dev_info; | 791 | current->backing_dev_info = mapping->backing_dev_info; |
834 | 792 | ||
835 | if (!(ioflags & IO_ISDIRECT)) { | ||
836 | int enospc = 0; | ||
837 | |||
838 | write_retry: | 793 | write_retry: |
839 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, ioflags); | 794 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); |
840 | ret = generic_file_buffered_write(iocb, iovp, nr_segs, | 795 | ret = generic_file_buffered_write(iocb, iovp, nr_segs, |
841 | pos, &iocb->ki_pos, count, ret); | 796 | pos, &iocb->ki_pos, count, ret); |
842 | /* | 797 | /* |
843 | * if we just got an ENOSPC, flush the inode now we | 798 | * if we just got an ENOSPC, flush the inode now we aren't holding any |
844 | * aren't holding any page locks and retry *once* | 799 | * page locks and retry *once* |
845 | */ | 800 | */ |
846 | if (ret == -ENOSPC && !enospc) { | 801 | if (ret == -ENOSPC && !enospc) { |
847 | ret = xfs_flush_pages(ip, 0, -1, 0, FI_NONE); | 802 | ret = -xfs_flush_pages(ip, 0, -1, 0, FI_NONE); |
848 | if (ret) | 803 | if (ret) |
849 | goto out_unlock_internal; | 804 | return ret; |
850 | enospc = 1; | 805 | enospc = 1; |
851 | goto write_retry; | 806 | goto write_retry; |
852 | } | ||
853 | } | 807 | } |
854 | |||
855 | current->backing_dev_info = NULL; | 808 | current->backing_dev_info = NULL; |
809 | return ret; | ||
810 | } | ||
811 | |||
812 | STATIC ssize_t | ||
813 | xfs_file_aio_write( | ||
814 | struct kiocb *iocb, | ||
815 | const struct iovec *iovp, | ||
816 | unsigned long nr_segs, | ||
817 | loff_t pos) | ||
818 | { | ||
819 | struct file *file = iocb->ki_filp; | ||
820 | struct address_space *mapping = file->f_mapping; | ||
821 | struct inode *inode = mapping->host; | ||
822 | struct xfs_inode *ip = XFS_I(inode); | ||
823 | ssize_t ret; | ||
824 | int iolock; | ||
825 | size_t ocount = 0; | ||
826 | |||
827 | XFS_STATS_INC(xs_write_calls); | ||
828 | |||
829 | BUG_ON(iocb->ki_pos != pos); | ||
830 | |||
831 | ret = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ); | ||
832 | if (ret) | ||
833 | return ret; | ||
834 | |||
835 | if (ocount == 0) | ||
836 | return 0; | ||
837 | |||
838 | xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); | ||
839 | |||
840 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
841 | return -EIO; | ||
842 | |||
843 | if (unlikely(file->f_flags & O_DIRECT)) | ||
844 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, | ||
845 | ocount, &iolock); | ||
846 | else | ||
847 | ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos, | ||
848 | ocount, &iolock); | ||
856 | 849 | ||
857 | done_io: | ||
858 | xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret); | 850 | xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret); |
859 | 851 | ||
860 | if (ret <= 0) | 852 | if (ret <= 0) |
861 | goto out_unlock_internal; | 853 | goto out_unlock; |
862 | 854 | ||
863 | /* Handle various SYNC-type writes */ | 855 | /* Handle various SYNC-type writes */ |
864 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { | 856 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { |
@@ -877,7 +869,7 @@ done_io: | |||
877 | ret = error2; | 869 | ret = error2; |
878 | } | 870 | } |
879 | 871 | ||
880 | out_unlock_internal: | 872 | out_unlock: |
881 | xfs_aio_write_newsize_update(ip); | 873 | xfs_aio_write_newsize_update(ip); |
882 | xfs_rw_iunlock(ip, iolock); | 874 | xfs_rw_iunlock(ip, iolock); |
883 | return ret; | 875 | return ret; |