aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-10-12 03:55:07 -0400
committerBen Myers <bpm@sgi.com>2013-10-21 17:56:21 -0400
commit83aee9e4c2976143f35b3a42ad1faadf58c53ae7 (patch)
tree568ca76e660645e9762f14c1972514b7f59f247c /fs
parent5f8aca8b43f41c4b2d4dc5389124a40cab92b644 (diff)
xfs: simplify the fallocate path
Call xfs_alloc_file_space or xfs_free_file_space directly from xfs_file_fallocate instead of going through xfs_change_file_space. This simplified the code by removing the unessecary marshalling of the arguments into an xfs_flock64_t structure and allows removing checks that are already done in the VFS code. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_bmap_util.c39
-rw-r--r--fs/xfs/xfs_bmap_util.h4
-rw-r--r--fs/xfs/xfs_file.c76
3 files changed, 56 insertions, 63 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index bdd552d83107..7e1c2ae81c35 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -965,28 +965,9 @@ xfs_free_eofblocks(
965 return error; 965 return error;
966} 966}
967 967
968/* 968int
969 * xfs_alloc_file_space()
970 * This routine allocates disk space for the given file.
971 *
972 * If alloc_type == 0, this request is for an ALLOCSP type
973 * request which will change the file size. In this case, no
974 * DMAPI event will be generated by the call. A TRUNCATE event
975 * will be generated later by xfs_setattr.
976 *
977 * If alloc_type != 0, this request is for a RESVSP type
978 * request, and a DMAPI DM_EVENT_WRITE will be generated if the
979 * lower block boundary byte address is less than the file's
980 * length.
981 *
982 * RETURNS:
983 * 0 on success
984 * errno on error
985 *
986 */
987STATIC int
988xfs_alloc_file_space( 969xfs_alloc_file_space(
989 xfs_inode_t *ip, 970 struct xfs_inode *ip,
990 xfs_off_t offset, 971 xfs_off_t offset,
991 xfs_off_t len, 972 xfs_off_t len,
992 int alloc_type) 973 int alloc_type)
@@ -1231,21 +1212,9 @@ xfs_zero_remaining_bytes(
1231 return error; 1212 return error;
1232} 1213}
1233 1214
1234/* 1215int
1235 * xfs_free_file_space()
1236 * This routine frees disk space for the given file.
1237 *
1238 * This routine is only called by xfs_change_file_space
1239 * for an UNRESVSP type call.
1240 *
1241 * RETURNS:
1242 * 0 on success
1243 * errno on error
1244 *
1245 */
1246STATIC int
1247xfs_free_file_space( 1216xfs_free_file_space(
1248 xfs_inode_t *ip, 1217 struct xfs_inode *ip,
1249 xfs_off_t offset, 1218 xfs_off_t offset,
1250 xfs_off_t len) 1219 xfs_off_t len)
1251{ 1220{
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 061260946f7a..77cf5001719b 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -96,6 +96,10 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
96int xfs_change_file_space(struct xfs_inode *ip, int cmd, 96int xfs_change_file_space(struct xfs_inode *ip, int cmd,
97 xfs_flock64_t *bf, xfs_off_t offset, 97 xfs_flock64_t *bf, xfs_off_t offset,
98 int attr_flags); 98 int attr_flags);
99int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
100 xfs_off_t len, int alloc_type);
101int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
102 xfs_off_t len);
99 103
100/* EOF block manipulation functions */ 104/* EOF block manipulation functions */
101bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); 105bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 116300f3b1d4..c8a75a75e25a 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -805,44 +805,64 @@ out:
805 805
806STATIC long 806STATIC long
807xfs_file_fallocate( 807xfs_file_fallocate(
808 struct file *file, 808 struct file *file,
809 int mode, 809 int mode,
810 loff_t offset, 810 loff_t offset,
811 loff_t len) 811 loff_t len)
812{ 812{
813 struct inode *inode = file_inode(file); 813 struct inode *inode = file_inode(file);
814 long error; 814 struct xfs_inode *ip = XFS_I(inode);
815 loff_t new_size = 0; 815 struct xfs_trans *tp;
816 xfs_flock64_t bf; 816 long error;
817 xfs_inode_t *ip = XFS_I(inode); 817 loff_t new_size = 0;
818 int cmd = XFS_IOC_RESVSP;
819 int attr_flags = 0;
820 818
819 if (!S_ISREG(inode->i_mode))
820 return -EINVAL;
821 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) 821 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
822 return -EOPNOTSUPP; 822 return -EOPNOTSUPP;
823 823
824 bf.l_whence = 0;
825 bf.l_start = offset;
826 bf.l_len = len;
827
828 xfs_ilock(ip, XFS_IOLOCK_EXCL); 824 xfs_ilock(ip, XFS_IOLOCK_EXCL);
825 if (mode & FALLOC_FL_PUNCH_HOLE) {
826 error = xfs_free_file_space(ip, offset, len);
827 if (error)
828 goto out_unlock;
829 } else {
830 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
831 offset + len > i_size_read(inode)) {
832 new_size = offset + len;
833 error = -inode_newsize_ok(inode, new_size);
834 if (error)
835 goto out_unlock;
836 }
829 837
830 if (mode & FALLOC_FL_PUNCH_HOLE) 838 error = xfs_alloc_file_space(ip, offset, len,
831 cmd = XFS_IOC_UNRESVSP; 839 XFS_BMAPI_PREALLOC);
832
833 /* check the new inode size is valid before allocating */
834 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
835 offset + len > i_size_read(inode)) {
836 new_size = offset + len;
837 error = inode_newsize_ok(inode, new_size);
838 if (error) 840 if (error)
839 goto out_unlock; 841 goto out_unlock;
840 } 842 }
841 843
842 if (file->f_flags & O_DSYNC) 844 tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
843 attr_flags |= XFS_ATTR_SYNC; 845 error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0);
846 if (error) {
847 xfs_trans_cancel(tp, 0);
848 goto out_unlock;
849 }
850
851 xfs_ilock(ip, XFS_ILOCK_EXCL);
852 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
853 ip->i_d.di_mode &= ~S_ISUID;
854 if (ip->i_d.di_mode & S_IXGRP)
855 ip->i_d.di_mode &= ~S_ISGID;
856
857 if (!(mode & FALLOC_FL_PUNCH_HOLE))
858 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
859
860 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
861 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
844 862
845 error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); 863 if (file->f_flags & O_DSYNC)
864 xfs_trans_set_sync(tp);
865 error = xfs_trans_commit(tp, 0);
846 if (error) 866 if (error)
847 goto out_unlock; 867 goto out_unlock;
848 868
@@ -852,12 +872,12 @@ xfs_file_fallocate(
852 872
853 iattr.ia_valid = ATTR_SIZE; 873 iattr.ia_valid = ATTR_SIZE;
854 iattr.ia_size = new_size; 874 iattr.ia_size = new_size;
855 error = -xfs_setattr_size(ip, &iattr); 875 error = xfs_setattr_size(ip, &iattr);
856 } 876 }
857 877
858out_unlock: 878out_unlock:
859 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 879 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
860 return error; 880 return -error;
861} 881}
862 882
863 883