aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c61
1 files changed, 32 insertions, 29 deletions
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 8e46c9798fb..80fe3123347 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -649,7 +649,7 @@ xfs_write(
649 bhv_vrwlock_t locktype; 649 bhv_vrwlock_t locktype;
650 size_t ocount = 0, count; 650 size_t ocount = 0, count;
651 loff_t pos; 651 loff_t pos;
652 int need_i_mutex = 1, need_flush = 0; 652 int need_i_mutex;
653 653
654 XFS_STATS_INC(xs_write_calls); 654 XFS_STATS_INC(xs_write_calls);
655 655
@@ -689,39 +689,20 @@ xfs_write(
689 if (XFS_FORCED_SHUTDOWN(mp)) 689 if (XFS_FORCED_SHUTDOWN(mp))
690 return -EIO; 690 return -EIO;
691 691
692 if (ioflags & IO_ISDIRECT) {
693 xfs_buftarg_t *target =
694 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
695 mp->m_rtdev_targp : mp->m_ddev_targp;
696
697 if ((pos & target->bt_smask) || (count & target->bt_smask))
698 return XFS_ERROR(-EINVAL);
699
700 if (!VN_CACHED(vp) && pos < i_size_read(inode))
701 need_i_mutex = 0;
702
703 if (VN_CACHED(vp))
704 need_flush = 1;
705 }
706
707relock: 692relock:
708 if (need_i_mutex) { 693 if (ioflags & IO_ISDIRECT) {
694 iolock = XFS_IOLOCK_SHARED;
695 locktype = VRWLOCK_WRITE_DIRECT;
696 need_i_mutex = 0;
697 } else {
709 iolock = XFS_IOLOCK_EXCL; 698 iolock = XFS_IOLOCK_EXCL;
710 locktype = VRWLOCK_WRITE; 699 locktype = VRWLOCK_WRITE;
711 700 need_i_mutex = 1;
712 mutex_lock(&inode->i_mutex); 701 mutex_lock(&inode->i_mutex);
713 } else {
714 iolock = XFS_IOLOCK_SHARED;
715 locktype = VRWLOCK_WRITE_DIRECT;
716 } 702 }
717 703
718 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock); 704 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
719 705
720 isize = i_size_read(inode);
721
722 if (file->f_flags & O_APPEND)
723 *offset = isize;
724
725start: 706start:
726 error = -generic_write_checks(file, &pos, &count, 707 error = -generic_write_checks(file, &pos, &count,
727 S_ISBLK(inode->i_mode)); 708 S_ISBLK(inode->i_mode));
@@ -730,6 +711,29 @@ start:
730 goto out_unlock_mutex; 711 goto out_unlock_mutex;
731 } 712 }
732 713
714 isize = i_size_read(inode);
715
716 if (ioflags & IO_ISDIRECT) {
717 xfs_buftarg_t *target =
718 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
719 mp->m_rtdev_targp : mp->m_ddev_targp;
720
721 if ((pos & target->bt_smask) || (count & target->bt_smask)) {
722 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
723 return XFS_ERROR(-EINVAL);
724 }
725
726 if (!need_i_mutex && (VN_CACHED(vp) || pos > isize)) {
727 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
728 iolock = XFS_IOLOCK_EXCL;
729 locktype = VRWLOCK_WRITE;
730 need_i_mutex = 1;
731 mutex_lock(&inode->i_mutex);
732 xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
733 goto start;
734 }
735 }
736
733 new_size = pos + count; 737 new_size = pos + count;
734 if (new_size > isize) 738 if (new_size > isize)
735 io->io_new_size = new_size; 739 io->io_new_size = new_size;
@@ -761,7 +765,6 @@ start:
761 * what allows the size to change in the first place. 765 * what allows the size to change in the first place.
762 */ 766 */
763 if ((file->f_flags & O_APPEND) && savedsize != isize) { 767 if ((file->f_flags & O_APPEND) && savedsize != isize) {
764 pos = isize = xip->i_d.di_size;
765 goto start; 768 goto start;
766 } 769 }
767 } 770 }
@@ -815,7 +818,8 @@ retry:
815 current->backing_dev_info = mapping->backing_dev_info; 818 current->backing_dev_info = mapping->backing_dev_info;
816 819
817 if ((ioflags & IO_ISDIRECT)) { 820 if ((ioflags & IO_ISDIRECT)) {
818 if (need_flush) { 821 if (VN_CACHED(vp)) {
822 WARN_ON(need_i_mutex == 0);
819 xfs_inval_cached_trace(io, pos, -1, 823 xfs_inval_cached_trace(io, pos, -1,
820 ctooff(offtoct(pos)), -1); 824 ctooff(offtoct(pos)), -1);
821 error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)), 825 error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
@@ -849,7 +853,6 @@ retry:
849 pos += ret; 853 pos += ret;
850 count -= ret; 854 count -= ret;
851 855
852 need_i_mutex = 1;
853 ioflags &= ~IO_ISDIRECT; 856 ioflags &= ~IO_ISDIRECT;
854 xfs_iunlock(xip, iolock); 857 xfs_iunlock(xip, iolock);
855 goto relock; 858 goto relock;