diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index ef51eb43e137..a55c1b46b219 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "xfs_trace.h" | 37 | #include "xfs_trace.h" |
38 | 38 | ||
39 | #include <linux/dcache.h> | 39 | #include <linux/dcache.h> |
40 | #include <linux/falloc.h> | ||
40 | 41 | ||
41 | static const struct vm_operations_struct xfs_file_vm_ops; | 42 | static const struct vm_operations_struct xfs_file_vm_ops; |
42 | 43 | ||
@@ -882,6 +883,60 @@ out_unlock: | |||
882 | return ret; | 883 | return ret; |
883 | } | 884 | } |
884 | 885 | ||
886 | STATIC long | ||
887 | xfs_file_fallocate( | ||
888 | struct file *file, | ||
889 | int mode, | ||
890 | loff_t offset, | ||
891 | loff_t len) | ||
892 | { | ||
893 | struct inode *inode = file->f_path.dentry->d_inode; | ||
894 | long error; | ||
895 | loff_t new_size = 0; | ||
896 | xfs_flock64_t bf; | ||
897 | xfs_inode_t *ip = XFS_I(inode); | ||
898 | int cmd = XFS_IOC_RESVSP; | ||
899 | |||
900 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) | ||
901 | return -EOPNOTSUPP; | ||
902 | |||
903 | bf.l_whence = 0; | ||
904 | bf.l_start = offset; | ||
905 | bf.l_len = len; | ||
906 | |||
907 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
908 | |||
909 | if (mode & FALLOC_FL_PUNCH_HOLE) | ||
910 | cmd = XFS_IOC_UNRESVSP; | ||
911 | |||
912 | /* check the new inode size is valid before allocating */ | ||
913 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | ||
914 | offset + len > i_size_read(inode)) { | ||
915 | new_size = offset + len; | ||
916 | error = inode_newsize_ok(inode, new_size); | ||
917 | if (error) | ||
918 | goto out_unlock; | ||
919 | } | ||
920 | |||
921 | error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK); | ||
922 | if (error) | ||
923 | goto out_unlock; | ||
924 | |||
925 | /* Change file size if needed */ | ||
926 | if (new_size) { | ||
927 | struct iattr iattr; | ||
928 | |||
929 | iattr.ia_valid = ATTR_SIZE; | ||
930 | iattr.ia_size = new_size; | ||
931 | error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK); | ||
932 | } | ||
933 | |||
934 | out_unlock: | ||
935 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
936 | return error; | ||
937 | } | ||
938 | |||
939 | |||
885 | STATIC int | 940 | STATIC int |
886 | xfs_file_open( | 941 | xfs_file_open( |
887 | struct inode *inode, | 942 | struct inode *inode, |
@@ -1000,6 +1055,7 @@ const struct file_operations xfs_file_operations = { | |||
1000 | .open = xfs_file_open, | 1055 | .open = xfs_file_open, |
1001 | .release = xfs_file_release, | 1056 | .release = xfs_file_release, |
1002 | .fsync = xfs_file_fsync, | 1057 | .fsync = xfs_file_fsync, |
1058 | .fallocate = xfs_file_fallocate, | ||
1003 | }; | 1059 | }; |
1004 | 1060 | ||
1005 | const struct file_operations xfs_dir_file_operations = { | 1061 | const struct file_operations xfs_dir_file_operations = { |