diff options
author | Christoph Hellwig <hch@lst.de> | 2015-02-01 17:53:56 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-02-01 17:53:56 -0500 |
commit | 8add71ca3fd67c5f222622711f95cfd6cec2a996 (patch) | |
tree | 63e6239dd7fc8fbf5b055f3abe683b7675679b7f /fs | |
parent | 4d949021aac8b63c9c3b8a83cc8a29759c7e1d5e (diff) |
xfs: factor out a xfs_update_prealloc_flags() helper
This logic is duplicated in xfs_file_fallocate and xfs_ioc_space, and
we'll need another copy of it for pNFS block support.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_file.c | 64 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 50 |
3 files changed, 63 insertions, 60 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 13e974e6a889..712d312d8e3e 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -127,6 +127,42 @@ xfs_iozero( | |||
127 | return (-status); | 127 | return (-status); |
128 | } | 128 | } |
129 | 129 | ||
130 | int | ||
131 | xfs_update_prealloc_flags( | ||
132 | struct xfs_inode *ip, | ||
133 | enum xfs_prealloc_flags flags) | ||
134 | { | ||
135 | struct xfs_trans *tp; | ||
136 | int error; | ||
137 | |||
138 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); | ||
139 | error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); | ||
140 | if (error) { | ||
141 | xfs_trans_cancel(tp, 0); | ||
142 | return error; | ||
143 | } | ||
144 | |||
145 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
146 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
147 | |||
148 | if (!(flags & XFS_PREALLOC_INVISIBLE)) { | ||
149 | ip->i_d.di_mode &= ~S_ISUID; | ||
150 | if (ip->i_d.di_mode & S_IXGRP) | ||
151 | ip->i_d.di_mode &= ~S_ISGID; | ||
152 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
153 | } | ||
154 | |||
155 | if (flags & XFS_PREALLOC_SET) | ||
156 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
157 | if (flags & XFS_PREALLOC_CLEAR) | ||
158 | ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; | ||
159 | |||
160 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
161 | if (flags & XFS_PREALLOC_SYNC) | ||
162 | xfs_trans_set_sync(tp); | ||
163 | return xfs_trans_commit(tp, 0); | ||
164 | } | ||
165 | |||
130 | /* | 166 | /* |
131 | * Fsync operations on directories are much simpler than on regular files, | 167 | * Fsync operations on directories are much simpler than on regular files, |
132 | * as there is no file data to flush, and thus also no need for explicit | 168 | * as there is no file data to flush, and thus also no need for explicit |
@@ -784,8 +820,8 @@ xfs_file_fallocate( | |||
784 | { | 820 | { |
785 | struct inode *inode = file_inode(file); | 821 | struct inode *inode = file_inode(file); |
786 | struct xfs_inode *ip = XFS_I(inode); | 822 | struct xfs_inode *ip = XFS_I(inode); |
787 | struct xfs_trans *tp; | ||
788 | long error; | 823 | long error; |
824 | enum xfs_prealloc_flags flags = 0; | ||
789 | loff_t new_size = 0; | 825 | loff_t new_size = 0; |
790 | 826 | ||
791 | if (!S_ISREG(inode->i_mode)) | 827 | if (!S_ISREG(inode->i_mode)) |
@@ -822,6 +858,8 @@ xfs_file_fallocate( | |||
822 | if (error) | 858 | if (error) |
823 | goto out_unlock; | 859 | goto out_unlock; |
824 | } else { | 860 | } else { |
861 | flags |= XFS_PREALLOC_SET; | ||
862 | |||
825 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 863 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
826 | offset + len > i_size_read(inode)) { | 864 | offset + len > i_size_read(inode)) { |
827 | new_size = offset + len; | 865 | new_size = offset + len; |
@@ -839,28 +877,10 @@ xfs_file_fallocate( | |||
839 | goto out_unlock; | 877 | goto out_unlock; |
840 | } | 878 | } |
841 | 879 | ||
842 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); | ||
843 | error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); | ||
844 | if (error) { | ||
845 | xfs_trans_cancel(tp, 0); | ||
846 | goto out_unlock; | ||
847 | } | ||
848 | |||
849 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
850 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
851 | ip->i_d.di_mode &= ~S_ISUID; | ||
852 | if (ip->i_d.di_mode & S_IXGRP) | ||
853 | ip->i_d.di_mode &= ~S_ISGID; | ||
854 | |||
855 | if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE))) | ||
856 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
857 | |||
858 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
859 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
860 | |||
861 | if (file->f_flags & O_DSYNC) | 880 | if (file->f_flags & O_DSYNC) |
862 | xfs_trans_set_sync(tp); | 881 | flags |= XFS_PREALLOC_SYNC; |
863 | error = xfs_trans_commit(tp, 0); | 882 | |
883 | error = xfs_update_prealloc_flags(ip, flags); | ||
864 | if (error) | 884 | if (error) |
865 | goto out_unlock; | 885 | goto out_unlock; |
866 | 886 | ||
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4ed2ba9342dc..bc220bcedded 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -377,6 +377,15 @@ int xfs_droplink(struct xfs_trans *, struct xfs_inode *); | |||
377 | int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); | 377 | int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); |
378 | 378 | ||
379 | /* from xfs_file.c */ | 379 | /* from xfs_file.c */ |
380 | enum xfs_prealloc_flags { | ||
381 | XFS_PREALLOC_SET = (1 << 1), | ||
382 | XFS_PREALLOC_CLEAR = (1 << 2), | ||
383 | XFS_PREALLOC_SYNC = (1 << 3), | ||
384 | XFS_PREALLOC_INVISIBLE = (1 << 4), | ||
385 | }; | ||
386 | |||
387 | int xfs_update_prealloc_flags(struct xfs_inode *, | ||
388 | enum xfs_prealloc_flags); | ||
380 | int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); | 389 | int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); |
381 | int xfs_iozero(struct xfs_inode *, loff_t, size_t); | 390 | int xfs_iozero(struct xfs_inode *, loff_t, size_t); |
382 | 391 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index a1831980a68e..d58bcd28f5f8 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -606,11 +606,8 @@ xfs_ioc_space( | |||
606 | unsigned int cmd, | 606 | unsigned int cmd, |
607 | xfs_flock64_t *bf) | 607 | xfs_flock64_t *bf) |
608 | { | 608 | { |
609 | struct xfs_mount *mp = ip->i_mount; | ||
610 | struct xfs_trans *tp; | ||
611 | struct iattr iattr; | 609 | struct iattr iattr; |
612 | bool setprealloc = false; | 610 | enum xfs_prealloc_flags flags = 0; |
613 | bool clrprealloc = false; | ||
614 | int error; | 611 | int error; |
615 | 612 | ||
616 | /* | 613 | /* |
@@ -630,6 +627,11 @@ xfs_ioc_space( | |||
630 | if (!S_ISREG(inode->i_mode)) | 627 | if (!S_ISREG(inode->i_mode)) |
631 | return -EINVAL; | 628 | return -EINVAL; |
632 | 629 | ||
630 | if (filp->f_flags & O_DSYNC) | ||
631 | flags |= XFS_PREALLOC_SYNC; | ||
632 | if (ioflags & XFS_IO_INVIS) | ||
633 | flags |= XFS_PREALLOC_INVISIBLE; | ||
634 | |||
633 | error = mnt_want_write_file(filp); | 635 | error = mnt_want_write_file(filp); |
634 | if (error) | 636 | if (error) |
635 | return error; | 637 | return error; |
@@ -673,25 +675,23 @@ xfs_ioc_space( | |||
673 | } | 675 | } |
674 | 676 | ||
675 | if (bf->l_start < 0 || | 677 | if (bf->l_start < 0 || |
676 | bf->l_start > mp->m_super->s_maxbytes || | 678 | bf->l_start > inode->i_sb->s_maxbytes || |
677 | bf->l_start + bf->l_len < 0 || | 679 | bf->l_start + bf->l_len < 0 || |
678 | bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) { | 680 | bf->l_start + bf->l_len >= inode->i_sb->s_maxbytes) { |
679 | error = -EINVAL; | 681 | error = -EINVAL; |
680 | goto out_unlock; | 682 | goto out_unlock; |
681 | } | 683 | } |
682 | 684 | ||
683 | switch (cmd) { | 685 | switch (cmd) { |
684 | case XFS_IOC_ZERO_RANGE: | 686 | case XFS_IOC_ZERO_RANGE: |
687 | flags |= XFS_PREALLOC_SET; | ||
685 | error = xfs_zero_file_space(ip, bf->l_start, bf->l_len); | 688 | error = xfs_zero_file_space(ip, bf->l_start, bf->l_len); |
686 | if (!error) | ||
687 | setprealloc = true; | ||
688 | break; | 689 | break; |
689 | case XFS_IOC_RESVSP: | 690 | case XFS_IOC_RESVSP: |
690 | case XFS_IOC_RESVSP64: | 691 | case XFS_IOC_RESVSP64: |
692 | flags |= XFS_PREALLOC_SET; | ||
691 | error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len, | 693 | error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len, |
692 | XFS_BMAPI_PREALLOC); | 694 | XFS_BMAPI_PREALLOC); |
693 | if (!error) | ||
694 | setprealloc = true; | ||
695 | break; | 695 | break; |
696 | case XFS_IOC_UNRESVSP: | 696 | case XFS_IOC_UNRESVSP: |
697 | case XFS_IOC_UNRESVSP64: | 697 | case XFS_IOC_UNRESVSP64: |
@@ -701,6 +701,7 @@ xfs_ioc_space( | |||
701 | case XFS_IOC_ALLOCSP64: | 701 | case XFS_IOC_ALLOCSP64: |
702 | case XFS_IOC_FREESP: | 702 | case XFS_IOC_FREESP: |
703 | case XFS_IOC_FREESP64: | 703 | case XFS_IOC_FREESP64: |
704 | flags |= XFS_PREALLOC_CLEAR; | ||
704 | if (bf->l_start > XFS_ISIZE(ip)) { | 705 | if (bf->l_start > XFS_ISIZE(ip)) { |
705 | error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), | 706 | error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), |
706 | bf->l_start - XFS_ISIZE(ip), 0); | 707 | bf->l_start - XFS_ISIZE(ip), 0); |
@@ -712,8 +713,6 @@ xfs_ioc_space( | |||
712 | iattr.ia_size = bf->l_start; | 713 | iattr.ia_size = bf->l_start; |
713 | 714 | ||
714 | error = xfs_setattr_size(ip, &iattr); | 715 | error = xfs_setattr_size(ip, &iattr); |
715 | if (!error) | ||
716 | clrprealloc = true; | ||
717 | break; | 716 | break; |
718 | default: | 717 | default: |
719 | ASSERT(0); | 718 | ASSERT(0); |
@@ -723,32 +722,7 @@ xfs_ioc_space( | |||
723 | if (error) | 722 | if (error) |
724 | goto out_unlock; | 723 | goto out_unlock; |
725 | 724 | ||
726 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); | 725 | error = xfs_update_prealloc_flags(ip, flags); |
727 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0); | ||
728 | if (error) { | ||
729 | xfs_trans_cancel(tp, 0); | ||
730 | goto out_unlock; | ||
731 | } | ||
732 | |||
733 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
734 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
735 | |||
736 | if (!(ioflags & XFS_IO_INVIS)) { | ||
737 | ip->i_d.di_mode &= ~S_ISUID; | ||
738 | if (ip->i_d.di_mode & S_IXGRP) | ||
739 | ip->i_d.di_mode &= ~S_ISGID; | ||
740 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
741 | } | ||
742 | |||
743 | if (setprealloc) | ||
744 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
745 | else if (clrprealloc) | ||
746 | ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; | ||
747 | |||
748 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
749 | if (filp->f_flags & O_DSYNC) | ||
750 | xfs_trans_set_sync(tp); | ||
751 | error = xfs_trans_commit(tp, 0); | ||
752 | 726 | ||
753 | out_unlock: | 727 | out_unlock: |
754 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 728 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |