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:23:42 -0500
committerDave Chinner <david@fromorbit.com>2011-01-10 18:23:42 -0500
commit4d8d15812fd9bc96d0da11467d23e0373feae933 (patch)
tree8f81ae552502cd13259f289cfee110a89579ea59 /fs/xfs/linux-2.6/xfs_file.c
parent637bbc75d9fda57c7bc77ce5ee37e29a77a0520d (diff)
xfs: factor common write setup code
The buffered IO and direct IO write paths share a common set of checks and limiting code prior to issuing the write. Factor that into a common helper function. 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.c123
1 files changed, 56 insertions, 67 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index e2bcf51d292e..5863dd8f448c 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -629,6 +629,58 @@ out_lock:
629} 629}
630 630
631/* 631/*
632 * Common pre-write limit and setup checks.
633 *
634 * Returns with iolock held according to @iolock.
635 */
636STATIC ssize_t
637xfs_file_aio_write_checks(
638 struct file *file,
639 loff_t *pos,
640 size_t *count,
641 int *iolock)
642{
643 struct inode *inode = file->f_mapping->host;
644 struct xfs_inode *ip = XFS_I(inode);
645 xfs_fsize_t new_size;
646 int error = 0;
647
648 error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode));
649 if (error) {
650 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
651 *iolock = 0;
652 return error;
653 }
654
655 new_size = *pos + *count;
656 if (new_size > ip->i_size)
657 ip->i_new_size = new_size;
658
659 if (likely(!(file->f_mode & FMODE_NOCMTIME)))
660 file_update_time(file);
661
662 /*
663 * If the offset is beyond the size of the file, we need to zero any
664 * blocks that fall between the existing EOF and the start of this
665 * write.
666 */
667 if (*pos > ip->i_size)
668 error = -xfs_zero_eof(ip, *pos, ip->i_size);
669
670 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
671 if (error)
672 return error;
673
674 /*
675 * If we're writing the file then make sure to clear the setuid and
676 * setgid bits if the process is not being run by root. This keeps
677 * people from modifying setuid and setgid binaries.
678 */
679 return file_remove_suid(file);
680
681}
682
683/*
632 * xfs_file_dio_aio_write - handle direct IO writes 684 * xfs_file_dio_aio_write - handle direct IO writes
633 * 685 *
634 * Lock the inode appropriately to prepare for and issue a direct IO write. 686 * Lock the inode appropriately to prepare for and issue a direct IO write.
@@ -653,7 +705,6 @@ xfs_file_dio_aio_write(
653 struct xfs_inode *ip = XFS_I(inode); 705 struct xfs_inode *ip = XFS_I(inode);
654 struct xfs_mount *mp = ip->i_mount; 706 struct xfs_mount *mp = ip->i_mount;
655 ssize_t ret = 0; 707 ssize_t ret = 0;
656 xfs_fsize_t new_size;
657 size_t count = ocount; 708 size_t count = ocount;
658 struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ? 709 struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ?
659 mp->m_rtdev_targp : mp->m_ddev_targp; 710 mp->m_rtdev_targp : mp->m_ddev_targp;
@@ -674,45 +725,8 @@ xfs_file_dio_aio_write(
674 *iolock = XFS_IOLOCK_SHARED; 725 *iolock = XFS_IOLOCK_SHARED;
675 xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); 726 xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
676 727
677 ret = generic_write_checks(file, &pos, &count, 728 ret = xfs_file_aio_write_checks(file, &pos, &count, iolock);
678 S_ISBLK(inode->i_mode)); 729 if (ret)
679 if (ret) {
680 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
681 *iolock = 0;
682 return ret;
683 }
684
685 new_size = pos + count;
686 if (new_size > ip->i_size)
687 ip->i_new_size = new_size;
688
689 if (likely(!(file->f_mode & FMODE_NOCMTIME)))
690 file_update_time(file);
691
692 /*
693 * If the offset is beyond the size of the file, we have a couple of
694 * things to do. First, if there is already space allocated we need to
695 * either create holes or zero the disk or ...
696 *
697 * If there is a page where the previous size lands, we need to zero it
698 * out up to the new size.
699 */
700 if (pos > ip->i_size) {
701 ret = -xfs_zero_eof(ip, pos, ip->i_size);
702 if (ret) {
703 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
704 return ret;
705 }
706 }
707 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
708
709 /*
710 * If we're writing the file then make sure to clear the setuid and
711 * setgid bits if the process is not being run by root. This keeps
712 * people from modifying setuid and setgid binaries.
713 */
714 ret = file_remove_suid(file);
715 if (unlikely(ret))
716 return ret; 730 return ret;
717 731
718 if (mapping->nrpages) { 732 if (mapping->nrpages) {
@@ -753,38 +767,13 @@ xfs_file_buffered_aio_write(
753 struct xfs_inode *ip = XFS_I(inode); 767 struct xfs_inode *ip = XFS_I(inode);
754 ssize_t ret; 768 ssize_t ret;
755 int enospc = 0; 769 int enospc = 0;
756 xfs_fsize_t new_size;
757 size_t count = ocount; 770 size_t count = ocount;
758 771
759 *iolock = XFS_IOLOCK_EXCL; 772 *iolock = XFS_IOLOCK_EXCL;
760 xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); 773 xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
761 774
762 ret = generic_write_checks(file, &pos, &count, 775 ret = xfs_file_aio_write_checks(file, &pos, &count, iolock);
763 S_ISBLK(inode->i_mode)); 776 if (ret)
764 if (ret) {
765 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
766 *iolock = 0;
767 return ret;
768 }
769
770 new_size = pos + count;
771 if (new_size > ip->i_size)
772 ip->i_new_size = new_size;
773
774 if (likely(!(file->f_mode & FMODE_NOCMTIME)))
775 file_update_time(file);
776
777 if (pos > ip->i_size) {
778 ret = -xfs_zero_eof(ip, pos, ip->i_size);
779 if (ret) {
780 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
781 return ret;
782 }
783 }
784 xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
785
786 ret = file_remove_suid(file);
787 if (unlikely(ret))
788 return ret; 777 return ret;
789 778
790 /* We can write back this queue in page reclaim */ 779 /* We can write back this queue in page reclaim */