aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_file.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-01-10 18:13:53 -0500
committerDave Chinner <david@fromorbit.com>2011-01-10 18:13:53 -0500
commita363f0c2030cb9781e7e458f4a9e354b6c43d7ce (patch)
tree7152662c40e6754194c6810c7331c87cdc338cb6 /fs/xfs/linux-2.6/xfs_file.c
parentd0eb2f38b250b7d6c993adf81b0e4ded0565497e (diff)
xfs: ensure sync write errors are returned
xfs_file_aio_write() only returns the error from synchronous flushing of the data and inode if error == 0. At the point where error is being checked, it is guaranteed to be > 0. Therefore any errors returned by the data or fsync flush will never be returned. Fix the checks so we overwrite the current error once and only if an error really occurred. 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/xfs_file.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index ba8ad422a165..10b7fb4807a6 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -574,7 +574,7 @@ xfs_file_aio_write(
574 struct inode *inode = mapping->host; 574 struct inode *inode = mapping->host;
575 struct xfs_inode *ip = XFS_I(inode); 575 struct xfs_inode *ip = XFS_I(inode);
576 struct xfs_mount *mp = ip->i_mount; 576 struct xfs_mount *mp = ip->i_mount;
577 ssize_t ret = 0, error = 0; 577 ssize_t ret = 0;
578 int ioflags = 0; 578 int ioflags = 0;
579 xfs_fsize_t isize, new_size; 579 xfs_fsize_t isize, new_size;
580 int iolock; 580 int iolock;
@@ -590,9 +590,9 @@ xfs_file_aio_write(
590 if (file->f_mode & FMODE_NOCMTIME) 590 if (file->f_mode & FMODE_NOCMTIME)
591 ioflags |= IO_INVIS; 591 ioflags |= IO_INVIS;
592 592
593 error = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ); 593 ret = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ);
594 if (error) 594 if (ret)
595 return error; 595 return ret;
596 596
597 count = ocount; 597 count = ocount;
598 if (count == 0) 598 if (count == 0)
@@ -616,9 +616,9 @@ relock:
616 xfs_ilock(ip, XFS_ILOCK_EXCL|iolock); 616 xfs_ilock(ip, XFS_ILOCK_EXCL|iolock);
617 617
618start: 618start:
619 error = -generic_write_checks(file, &pos, &count, 619 ret = generic_write_checks(file, &pos, &count,
620 S_ISBLK(inode->i_mode)); 620 S_ISBLK(inode->i_mode));
621 if (error) { 621 if (ret) {
622 xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock); 622 xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
623 goto out_unlock_mutex; 623 goto out_unlock_mutex;
624 } 624 }
@@ -660,8 +660,8 @@ start:
660 */ 660 */
661 661
662 if (pos > ip->i_size) { 662 if (pos > ip->i_size) {
663 error = xfs_zero_eof(ip, pos, ip->i_size); 663 ret = -xfs_zero_eof(ip, pos, ip->i_size);
664 if (error) { 664 if (ret) {
665 xfs_iunlock(ip, XFS_ILOCK_EXCL); 665 xfs_iunlock(ip, XFS_ILOCK_EXCL);
666 goto out_unlock_internal; 666 goto out_unlock_internal;
667 } 667 }
@@ -674,8 +674,8 @@ start:
674 * by root. This keeps people from modifying setuid and 674 * by root. This keeps people from modifying setuid and
675 * setgid binaries. 675 * setgid binaries.
676 */ 676 */
677 error = -file_remove_suid(file); 677 ret = file_remove_suid(file);
678 if (unlikely(error)) 678 if (unlikely(ret))
679 goto out_unlock_internal; 679 goto out_unlock_internal;
680 680
681 /* We can write back this queue in page reclaim */ 681 /* We can write back this queue in page reclaim */
@@ -684,10 +684,10 @@ start:
684 if ((ioflags & IO_ISDIRECT)) { 684 if ((ioflags & IO_ISDIRECT)) {
685 if (mapping->nrpages) { 685 if (mapping->nrpages) {
686 WARN_ON(need_i_mutex == 0); 686 WARN_ON(need_i_mutex == 0);
687 error = xfs_flushinval_pages(ip, 687 ret = -xfs_flushinval_pages(ip,
688 (pos & PAGE_CACHE_MASK), 688 (pos & PAGE_CACHE_MASK),
689 -1, FI_REMAPF_LOCKED); 689 -1, FI_REMAPF_LOCKED);
690 if (error) 690 if (ret)
691 goto out_unlock_internal; 691 goto out_unlock_internal;
692 } 692 }
693 693
@@ -720,24 +720,22 @@ start:
720 } 720 }
721 } else { 721 } else {
722 int enospc = 0; 722 int enospc = 0;
723 ssize_t ret2 = 0;
724 723
725write_retry: 724write_retry:
726 trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, ioflags); 725 trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, ioflags);
727 ret2 = generic_file_buffered_write(iocb, iovp, nr_segs, 726 ret = generic_file_buffered_write(iocb, iovp, nr_segs,
728 pos, &iocb->ki_pos, count, ret); 727 pos, &iocb->ki_pos, count, ret);
729 /* 728 /*
730 * if we just got an ENOSPC, flush the inode now we 729 * if we just got an ENOSPC, flush the inode now we
731 * aren't holding any page locks and retry *once* 730 * aren't holding any page locks and retry *once*
732 */ 731 */
733 if (ret2 == -ENOSPC && !enospc) { 732 if (ret == -ENOSPC && !enospc) {
734 error = xfs_flush_pages(ip, 0, -1, 0, FI_NONE); 733 ret = xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
735 if (error) 734 if (ret)
736 goto out_unlock_internal; 735 goto out_unlock_internal;
737 enospc = 1; 736 enospc = 1;
738 goto write_retry; 737 goto write_retry;
739 } 738 }
740 ret = ret2;
741 } 739 }
742 740
743 current->backing_dev_info = NULL; 741 current->backing_dev_info = NULL;
@@ -753,7 +751,6 @@ write_retry:
753 xfs_iunlock(ip, XFS_ILOCK_EXCL); 751 xfs_iunlock(ip, XFS_ILOCK_EXCL);
754 } 752 }
755 753
756 error = -ret;
757 if (ret <= 0) 754 if (ret <= 0)
758 goto out_unlock_internal; 755 goto out_unlock_internal;
759 756
@@ -762,23 +759,23 @@ write_retry:
762 /* Handle various SYNC-type writes */ 759 /* Handle various SYNC-type writes */
763 if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { 760 if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
764 loff_t end = pos + ret - 1; 761 loff_t end = pos + ret - 1;
765 int error2; 762 int error, error2;
766 763
767 xfs_iunlock(ip, iolock); 764 xfs_iunlock(ip, iolock);
768 if (need_i_mutex) 765 if (need_i_mutex)
769 mutex_unlock(&inode->i_mutex); 766 mutex_unlock(&inode->i_mutex);
770 767
771 error2 = filemap_write_and_wait_range(mapping, pos, end); 768 error = filemap_write_and_wait_range(mapping, pos, end);
772 if (!error)
773 error = error2;
774 if (need_i_mutex) 769 if (need_i_mutex)
775 mutex_lock(&inode->i_mutex); 770 mutex_lock(&inode->i_mutex);
776 xfs_ilock(ip, iolock); 771 xfs_ilock(ip, iolock);
777 772
778 error2 = -xfs_file_fsync(file, 773 error2 = -xfs_file_fsync(file,
779 (file->f_flags & __O_SYNC) ? 0 : 1); 774 (file->f_flags & __O_SYNC) ? 0 : 1);
780 if (!error) 775 if (error)
781 error = error2; 776 ret = error;
777 else if (error2)
778 ret = error2;
782 } 779 }
783 780
784 out_unlock_internal: 781 out_unlock_internal:
@@ -800,7 +797,7 @@ write_retry:
800 out_unlock_mutex: 797 out_unlock_mutex:
801 if (need_i_mutex) 798 if (need_i_mutex)
802 mutex_unlock(&inode->i_mutex); 799 mutex_unlock(&inode->i_mutex);
803 return -error; 800 return ret;
804} 801}
805 802
806STATIC int 803STATIC int