diff options
author | Christoph Hellwig <hch@lst.de> | 2011-01-14 07:07:43 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-17 02:25:31 -0500 |
commit | 2fe17c1075836b66678ed2a305fd09b6773883aa (patch) | |
tree | eb5287be8138686682eef9622872cfc7657e0664 /fs/ext4 | |
parent | 64c23e86873ee410554d6d1c76b60da47025e96f (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/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/ext4/extents.c | 9 | ||||
-rw-r--r-- | fs/ext4/file.c | 2 |
3 files changed, 5 insertions, 8 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 1de65f572033..0c8d97b56f34 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2065,7 +2065,7 @@ extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
2065 | extern void ext4_ext_truncate(struct inode *); | 2065 | extern void ext4_ext_truncate(struct inode *); |
2066 | extern void ext4_ext_init(struct super_block *); | 2066 | extern void ext4_ext_init(struct super_block *); |
2067 | extern void ext4_ext_release(struct super_block *); | 2067 | extern void ext4_ext_release(struct super_block *); |
2068 | extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset, | 2068 | extern long ext4_fallocate(struct file *file, int mode, loff_t offset, |
2069 | loff_t len); | 2069 | loff_t len); |
2070 | extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, | 2070 | extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, |
2071 | ssize_t len); | 2071 | ssize_t len); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4bdd160854eb..63a75810b7c3 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3627,14 +3627,15 @@ static void ext4_falloc_update_inode(struct inode *inode, | |||
3627 | } | 3627 | } |
3628 | 3628 | ||
3629 | /* | 3629 | /* |
3630 | * preallocate space for a file. This implements ext4's fallocate inode | 3630 | * preallocate space for a file. This implements ext4's fallocate file |
3631 | * operation, which gets called from sys_fallocate system call. | 3631 | * operation, which gets called from sys_fallocate system call. |
3632 | * For block-mapped files, posix_fallocate should fall back to the method | 3632 | * For block-mapped files, posix_fallocate should fall back to the method |
3633 | * of writing zeroes to the required new blocks (the same behavior which is | 3633 | * of writing zeroes to the required new blocks (the same behavior which is |
3634 | * expected for file systems which do not support fallocate() system call). | 3634 | * expected for file systems which do not support fallocate() system call). |
3635 | */ | 3635 | */ |
3636 | long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | 3636 | long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
3637 | { | 3637 | { |
3638 | struct inode *inode = file->f_path.dentry->d_inode; | ||
3638 | handle_t *handle; | 3639 | handle_t *handle; |
3639 | loff_t new_size; | 3640 | loff_t new_size; |
3640 | unsigned int max_blocks; | 3641 | unsigned int max_blocks; |
@@ -3655,10 +3656,6 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | |||
3655 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 3656 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
3656 | return -EOPNOTSUPP; | 3657 | return -EOPNOTSUPP; |
3657 | 3658 | ||
3658 | /* preallocation to directories is currently not supported */ | ||
3659 | if (S_ISDIR(inode->i_mode)) | ||
3660 | return -ENODEV; | ||
3661 | |||
3662 | map.m_lblk = offset >> blkbits; | 3659 | map.m_lblk = offset >> blkbits; |
3663 | /* | 3660 | /* |
3664 | * We can't just convert len to max_blocks because | 3661 | * We can't just convert len to max_blocks because |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index bb003dc9ffff..2e8322c8aa88 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -210,6 +210,7 @@ const struct file_operations ext4_file_operations = { | |||
210 | .fsync = ext4_sync_file, | 210 | .fsync = ext4_sync_file, |
211 | .splice_read = generic_file_splice_read, | 211 | .splice_read = generic_file_splice_read, |
212 | .splice_write = generic_file_splice_write, | 212 | .splice_write = generic_file_splice_write, |
213 | .fallocate = ext4_fallocate, | ||
213 | }; | 214 | }; |
214 | 215 | ||
215 | const struct inode_operations ext4_file_inode_operations = { | 216 | const struct inode_operations ext4_file_inode_operations = { |
@@ -223,7 +224,6 @@ const struct inode_operations ext4_file_inode_operations = { | |||
223 | .removexattr = generic_removexattr, | 224 | .removexattr = generic_removexattr, |
224 | #endif | 225 | #endif |
225 | .check_acl = ext4_check_acl, | 226 | .check_acl = ext4_check_acl, |
226 | .fallocate = ext4_fallocate, | ||
227 | .fiemap = ext4_fiemap, | 227 | .fiemap = ext4_fiemap, |
228 | }; | 228 | }; |
229 | 229 | ||