aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-02-01 17:53:56 -0500
committerDave Chinner <david@fromorbit.com>2015-02-01 17:53:56 -0500
commit8add71ca3fd67c5f222622711f95cfd6cec2a996 (patch)
tree63e6239dd7fc8fbf5b055f3abe683b7675679b7f /fs
parent4d949021aac8b63c9c3b8a83cc8a29759c7e1d5e (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.c64
-rw-r--r--fs/xfs/xfs_inode.h9
-rw-r--r--fs/xfs/xfs_ioctl.c50
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
130int
131xfs_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 *);
377int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); 377int xfs_bumplink(struct xfs_trans *, struct xfs_inode *);
378 378
379/* from xfs_file.c */ 379/* from xfs_file.c */
380enum 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
387int xfs_update_prealloc_flags(struct xfs_inode *,
388 enum xfs_prealloc_flags);
380int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); 389int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
381int xfs_iozero(struct xfs_inode *, loff_t, size_t); 390int 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
753out_unlock: 727out_unlock:
754 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 728 xfs_iunlock(ip, XFS_IOLOCK_EXCL);