aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2011-01-14 07:07:43 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-17 02:25:31 -0500
commit2fe17c1075836b66678ed2a305fd09b6773883aa (patch)
treeeb5287be8138686682eef9622872cfc7657e0664 /fs/xfs
parent64c23e86873ee410554d6d1c76b60da47025e96f (diff)
fallocate should be a file operation
Currently all filesystems except XFS implement fallocate asynchronously, while XFS forced a commit. Both of these are suboptimal - in case of O_SYNC I/O we really want our allocation on disk, especially for the !KEEP_SIZE case where we actually grow the file with user-visible zeroes. On the other hand always commiting the transaction is a bad idea for fast-path uses of fallocate like for example in recent Samba versions. Given that block allocation is a data plane operation anyway change it from an inode operation to a file operation so that we have the file structure available that lets us check for O_SYNC. This also includes moving the code around for a few of the filesystems, and remove the already unnedded S_ISDIR checks given that we only wire up fallocate for regular files. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c56
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c60
2 files changed, 56 insertions, 60 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
41static const struct vm_operations_struct xfs_file_vm_ops; 42static 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
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
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
934out_unlock:
935 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
936 return error;
937}
938
939
885STATIC int 940STATIC int
886xfs_file_open( 941xfs_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
1005const struct file_operations xfs_dir_file_operations = { 1061const struct file_operations xfs_dir_file_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index a4ecc2188a09..bd5727852fd6 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -46,7 +46,6 @@
46#include <linux/namei.h> 46#include <linux/namei.h>
47#include <linux/posix_acl.h> 47#include <linux/posix_acl.h>
48#include <linux/security.h> 48#include <linux/security.h>
49#include <linux/falloc.h>
50#include <linux/fiemap.h> 49#include <linux/fiemap.h>
51#include <linux/slab.h> 50#include <linux/slab.h>
52 51
@@ -505,64 +504,6 @@ xfs_vn_setattr(
505 return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0); 504 return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0);
506} 505}
507 506
508STATIC long
509xfs_vn_fallocate(
510 struct inode *inode,
511 int mode,
512 loff_t offset,
513 loff_t len)
514{
515 long error;
516 loff_t new_size = 0;
517 xfs_flock64_t bf;
518 xfs_inode_t *ip = XFS_I(inode);
519 int cmd = XFS_IOC_RESVSP;
520
521 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
522 return -EOPNOTSUPP;
523
524 /* preallocation on directories not yet supported */
525 error = -ENODEV;
526 if (S_ISDIR(inode->i_mode))
527 goto out_error;
528
529 bf.l_whence = 0;
530 bf.l_start = offset;
531 bf.l_len = len;
532
533 xfs_ilock(ip, XFS_IOLOCK_EXCL);
534
535 if (mode & FALLOC_FL_PUNCH_HOLE)
536 cmd = XFS_IOC_UNRESVSP;
537
538 /* check the new inode size is valid before allocating */
539 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
540 offset + len > i_size_read(inode)) {
541 new_size = offset + len;
542 error = inode_newsize_ok(inode, new_size);
543 if (error)
544 goto out_unlock;
545 }
546
547 error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK);
548 if (error)
549 goto out_unlock;
550
551 /* Change file size if needed */
552 if (new_size) {
553 struct iattr iattr;
554
555 iattr.ia_valid = ATTR_SIZE;
556 iattr.ia_size = new_size;
557 error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
558 }
559
560out_unlock:
561 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
562out_error:
563 return error;
564}
565
566#define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) 507#define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
567 508
568/* 509/*
@@ -656,7 +597,6 @@ static const struct inode_operations xfs_inode_operations = {
656 .getxattr = generic_getxattr, 597 .getxattr = generic_getxattr,
657 .removexattr = generic_removexattr, 598 .removexattr = generic_removexattr,
658 .listxattr = xfs_vn_listxattr, 599 .listxattr = xfs_vn_listxattr,
659 .fallocate = xfs_vn_fallocate,
660 .fiemap = xfs_vn_fiemap, 600 .fiemap = xfs_vn_fiemap,
661}; 601};
662 602