aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
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/xfs/xfs_file.c
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/xfs/xfs_file.c')
-rw-r--r--fs/xfs/xfs_file.c64
1 files changed, 42 insertions, 22 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