aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_lrw.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_lrw.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c91
1 files changed, 55 insertions, 36 deletions
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 80fe31233471..82ab792c7fc9 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -224,7 +224,7 @@ xfs_read(
224 mp->m_rtdev_targp : mp->m_ddev_targp; 224 mp->m_rtdev_targp : mp->m_ddev_targp;
225 if ((*offset & target->bt_smask) || 225 if ((*offset & target->bt_smask) ||
226 (size & target->bt_smask)) { 226 (size & target->bt_smask)) {
227 if (*offset == ip->i_d.di_size) { 227 if (*offset == ip->i_size) {
228 return (0); 228 return (0);
229 } 229 }
230 return -XFS_ERROR(EINVAL); 230 return -XFS_ERROR(EINVAL);
@@ -387,9 +387,10 @@ xfs_splice_write(
387{ 387{
388 xfs_inode_t *ip = XFS_BHVTOI(bdp); 388 xfs_inode_t *ip = XFS_BHVTOI(bdp);
389 xfs_mount_t *mp = ip->i_mount; 389 xfs_mount_t *mp = ip->i_mount;
390 xfs_iocore_t *io = &ip->i_iocore;
390 ssize_t ret; 391 ssize_t ret;
391 struct inode *inode = outfilp->f_mapping->host; 392 struct inode *inode = outfilp->f_mapping->host;
392 xfs_fsize_t isize; 393 xfs_fsize_t isize, new_size;
393 394
394 XFS_STATS_INC(xs_write_calls); 395 XFS_STATS_INC(xs_write_calls);
395 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 396 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -410,6 +411,14 @@ xfs_splice_write(
410 return -error; 411 return -error;
411 } 412 }
412 } 413 }
414
415 new_size = *ppos + count;
416
417 xfs_ilock(ip, XFS_ILOCK_EXCL);
418 if (new_size > ip->i_size)
419 io->io_new_size = new_size;
420 xfs_iunlock(ip, XFS_ILOCK_EXCL);
421
413 xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore, 422 xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
414 pipe, count, *ppos, ioflags); 423 pipe, count, *ppos, ioflags);
415 ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); 424 ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
@@ -420,14 +429,18 @@ xfs_splice_write(
420 if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize)) 429 if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
421 *ppos = isize; 430 *ppos = isize;
422 431
423 if (*ppos > ip->i_d.di_size) { 432 if (*ppos > ip->i_size) {
424 xfs_ilock(ip, XFS_ILOCK_EXCL); 433 xfs_ilock(ip, XFS_ILOCK_EXCL);
425 if (*ppos > ip->i_d.di_size) { 434 if (*ppos > ip->i_size)
426 ip->i_d.di_size = *ppos; 435 ip->i_size = *ppos;
427 i_size_write(inode, *ppos); 436 xfs_iunlock(ip, XFS_ILOCK_EXCL);
428 ip->i_update_core = 1; 437 }
429 ip->i_update_size = 1; 438
430 } 439 if (io->io_new_size) {
440 xfs_ilock(ip, XFS_ILOCK_EXCL);
441 io->io_new_size = 0;
442 if (ip->i_d.di_size > ip->i_size)
443 ip->i_d.di_size = ip->i_size;
431 xfs_iunlock(ip, XFS_ILOCK_EXCL); 444 xfs_iunlock(ip, XFS_ILOCK_EXCL);
432 } 445 }
433 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 446 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
@@ -711,8 +724,6 @@ start:
711 goto out_unlock_mutex; 724 goto out_unlock_mutex;
712 } 725 }
713 726
714 isize = i_size_read(inode);
715
716 if (ioflags & IO_ISDIRECT) { 727 if (ioflags & IO_ISDIRECT) {
717 xfs_buftarg_t *target = 728 xfs_buftarg_t *target =
718 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? 729 (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
@@ -723,7 +734,7 @@ start:
723 return XFS_ERROR(-EINVAL); 734 return XFS_ERROR(-EINVAL);
724 } 735 }
725 736
726 if (!need_i_mutex && (VN_CACHED(vp) || pos > isize)) { 737 if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
727 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); 738 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
728 iolock = XFS_IOLOCK_EXCL; 739 iolock = XFS_IOLOCK_EXCL;
729 locktype = VRWLOCK_WRITE; 740 locktype = VRWLOCK_WRITE;
@@ -735,7 +746,7 @@ start:
735 } 746 }
736 747
737 new_size = pos + count; 748 new_size = pos + count;
738 if (new_size > isize) 749 if (new_size > xip->i_size)
739 io->io_new_size = new_size; 750 io->io_new_size = new_size;
740 751
741 if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) && 752 if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
@@ -751,8 +762,7 @@ start:
751 pos, count, 762 pos, count,
752 dmflags, &locktype); 763 dmflags, &locktype);
753 if (error) { 764 if (error) {
754 xfs_iunlock(xip, iolock); 765 goto out_unlock_internal;
755 goto out_unlock_mutex;
756 } 766 }
757 xfs_ilock(xip, XFS_ILOCK_EXCL); 767 xfs_ilock(xip, XFS_ILOCK_EXCL);
758 eventsent = 1; 768 eventsent = 1;
@@ -764,9 +774,8 @@ start:
764 * event prevents another call to XFS_SEND_DATA, which is 774 * event prevents another call to XFS_SEND_DATA, which is
765 * what allows the size to change in the first place. 775 * what allows the size to change in the first place.
766 */ 776 */
767 if ((file->f_flags & O_APPEND) && savedsize != isize) { 777 if ((file->f_flags & O_APPEND) && savedsize != xip->i_size)
768 goto start; 778 goto start;
769 }
770 } 779 }
771 780
772 if (likely(!(ioflags & IO_INVIS))) { 781 if (likely(!(ioflags & IO_INVIS))) {
@@ -784,11 +793,11 @@ start:
784 * to zero it out up to the new size. 793 * to zero it out up to the new size.
785 */ 794 */
786 795
787 if (pos > isize) { 796 if (pos > xip->i_size) {
788 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, isize); 797 error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
789 if (error) { 798 if (error) {
790 xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock); 799 xfs_iunlock(xip, XFS_ILOCK_EXCL);
791 goto out_unlock_mutex; 800 goto out_unlock_internal;
792 } 801 }
793 } 802 }
794 xfs_iunlock(xip, XFS_ILOCK_EXCL); 803 xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -808,8 +817,7 @@ start:
808 if (likely(!error)) 817 if (likely(!error))
809 error = -remove_suid(file->f_path.dentry); 818 error = -remove_suid(file->f_path.dentry);
810 if (unlikely(error)) { 819 if (unlikely(error)) {
811 xfs_iunlock(xip, iolock); 820 goto out_unlock_internal;
812 goto out_unlock_mutex;
813 } 821 }
814 } 822 }
815 823
@@ -879,12 +887,12 @@ retry:
879 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, 887 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
880 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, 888 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
881 0, 0, 0); /* Delay flag intentionally unused */ 889 0, 0, 0); /* Delay flag intentionally unused */
882 if (error)
883 goto out_nounlocks;
884 if (need_i_mutex) 890 if (need_i_mutex)
885 mutex_lock(&inode->i_mutex); 891 mutex_lock(&inode->i_mutex);
886 xfs_rwlock(bdp, locktype); 892 xfs_rwlock(bdp, locktype);
887 pos = xip->i_d.di_size; 893 if (error)
894 goto out_unlock_internal;
895 pos = xip->i_size;
888 ret = 0; 896 ret = 0;
889 goto retry; 897 goto retry;
890 } 898 }
@@ -893,14 +901,10 @@ retry:
893 if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize)) 901 if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
894 *offset = isize; 902 *offset = isize;
895 903
896 if (*offset > xip->i_d.di_size) { 904 if (*offset > xip->i_size) {
897 xfs_ilock(xip, XFS_ILOCK_EXCL); 905 xfs_ilock(xip, XFS_ILOCK_EXCL);
898 if (*offset > xip->i_d.di_size) { 906 if (*offset > xip->i_size)
899 xip->i_d.di_size = *offset; 907 xip->i_size = *offset;
900 i_size_write(inode, *offset);
901 xip->i_update_core = 1;
902 xip->i_update_size = 1;
903 }
904 xfs_iunlock(xip, XFS_ILOCK_EXCL); 908 xfs_iunlock(xip, XFS_ILOCK_EXCL);
905 } 909 }
906 910
@@ -922,16 +926,31 @@ retry:
922 926
923 error = sync_page_range(inode, mapping, pos, ret); 927 error = sync_page_range(inode, mapping, pos, ret);
924 if (!error) 928 if (!error)
925 error = ret; 929 error = -ret;
926 return error; 930 if (need_i_mutex)
931 mutex_lock(&inode->i_mutex);
932 xfs_rwlock(bdp, locktype);
927 } 933 }
928 934
929 out_unlock_internal: 935 out_unlock_internal:
936 if (io->io_new_size) {
937 xfs_ilock(xip, XFS_ILOCK_EXCL);
938 io->io_new_size = 0;
939 /*
940 * If this was a direct or synchronous I/O that failed (such
941 * as ENOSPC) then part of the I/O may have been written to
942 * disk before the error occured. In this case the on-disk
943 * file size may have been adjusted beyond the in-memory file
944 * size and now needs to be truncated back.
945 */
946 if (xip->i_d.di_size > xip->i_size)
947 xip->i_d.di_size = xip->i_size;
948 xfs_iunlock(xip, XFS_ILOCK_EXCL);
949 }
930 xfs_rwunlock(bdp, locktype); 950 xfs_rwunlock(bdp, locktype);
931 out_unlock_mutex: 951 out_unlock_mutex:
932 if (need_i_mutex) 952 if (need_i_mutex)
933 mutex_unlock(&inode->i_mutex); 953 mutex_unlock(&inode->i_mutex);
934 out_nounlocks:
935 return -error; 954 return -error;
936} 955}
937 956