aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index ef51eb43e137..f4213ba1ff85 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
41static const struct vm_operations_struct xfs_file_vm_ops; 42static const struct vm_operations_struct xfs_file_vm_ops;
42 43
@@ -380,7 +381,7 @@ xfs_aio_write_isize_update(
380 381
381/* 382/*
382 * If this was a direct or synchronous I/O that failed (such as ENOSPC) then 383 * If this was a direct or synchronous I/O that failed (such as ENOSPC) then
383 * part of the I/O may have been written to disk before the error occured. In 384 * part of the I/O may have been written to disk before the error occurred. In
384 * this case the on-disk file size may have been adjusted beyond the in-memory 385 * this case the on-disk file size may have been adjusted beyond the in-memory
385 * file size and now needs to be truncated back. 386 * file size and now needs to be truncated back.
386 */ 387 */
@@ -882,6 +883,64 @@ out_unlock:
882 return ret; 883 return ret;
883} 884}
884 885
886STATIC long
887xfs_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 int attr_flags = XFS_ATTR_NOLOCK;
900
901 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
902 return -EOPNOTSUPP;
903
904 bf.l_whence = 0;
905 bf.l_start = offset;
906 bf.l_len = len;
907
908 xfs_ilock(ip, XFS_IOLOCK_EXCL);
909
910 if (mode & FALLOC_FL_PUNCH_HOLE)
911 cmd = XFS_IOC_UNRESVSP;
912
913 /* check the new inode size is valid before allocating */
914 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
915 offset + len > i_size_read(inode)) {
916 new_size = offset + len;
917 error = inode_newsize_ok(inode, new_size);
918 if (error)
919 goto out_unlock;
920 }
921
922 if (file->f_flags & O_DSYNC)
923 attr_flags |= XFS_ATTR_SYNC;
924
925 error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags);
926 if (error)
927 goto out_unlock;
928
929 /* Change file size if needed */
930 if (new_size) {
931 struct iattr iattr;
932
933 iattr.ia_valid = ATTR_SIZE;
934 iattr.ia_size = new_size;
935 error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
936 }
937
938out_unlock:
939 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
940 return error;
941}
942
943
885STATIC int 944STATIC int
886xfs_file_open( 945xfs_file_open(
887 struct inode *inode, 946 struct inode *inode,
@@ -1000,6 +1059,7 @@ const struct file_operations xfs_file_operations = {
1000 .open = xfs_file_open, 1059 .open = xfs_file_open,
1001 .release = xfs_file_release, 1060 .release = xfs_file_release,
1002 .fsync = xfs_file_fsync, 1061 .fsync = xfs_file_fsync,
1062 .fallocate = xfs_file_fallocate,
1003}; 1063};
1004 1064
1005const struct file_operations xfs_dir_file_operations = { 1065const struct file_operations xfs_dir_file_operations = {