@@ -4690,6 +4690,58 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46904690 return ret ;
46914691}
46924692
4693+ static long ext4_do_fallocate (struct file * file , loff_t offset ,
4694+ loff_t len , int mode )
4695+ {
4696+ struct inode * inode = file_inode (file );
4697+ loff_t end = offset + len ;
4698+ loff_t new_size = 0 ;
4699+ ext4_lblk_t start_lblk , len_lblk ;
4700+ int ret ;
4701+
4702+ trace_ext4_fallocate_enter (inode , offset , len , mode );
4703+
4704+ start_lblk = offset >> inode -> i_blkbits ;
4705+ len_lblk = EXT4_MAX_BLOCKS (len , offset , inode -> i_blkbits );
4706+
4707+ inode_lock (inode );
4708+
4709+ /* We only support preallocation for extent-based files only. */
4710+ if (!(ext4_test_inode_flag (inode , EXT4_INODE_EXTENTS ))) {
4711+ ret = - EOPNOTSUPP ;
4712+ goto out ;
4713+ }
4714+
4715+ if (!(mode & FALLOC_FL_KEEP_SIZE ) &&
4716+ (end > inode -> i_size || end > EXT4_I (inode )-> i_disksize )) {
4717+ new_size = end ;
4718+ ret = inode_newsize_ok (inode , new_size );
4719+ if (ret )
4720+ goto out ;
4721+ }
4722+
4723+ /* Wait all existing dio workers, newcomers will block on i_rwsem */
4724+ inode_dio_wait (inode );
4725+
4726+ ret = file_modified (file );
4727+ if (ret )
4728+ goto out ;
4729+
4730+ ret = ext4_alloc_file_blocks (file , start_lblk , len_lblk , new_size ,
4731+ EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT );
4732+ if (ret )
4733+ goto out ;
4734+
4735+ if (file -> f_flags & O_SYNC && EXT4_SB (inode -> i_sb )-> s_journal ) {
4736+ ret = ext4_fc_commit (EXT4_SB (inode -> i_sb )-> s_journal ,
4737+ EXT4_I (inode )-> i_sync_tid );
4738+ }
4739+ out :
4740+ inode_unlock (inode );
4741+ trace_ext4_fallocate_exit (inode , offset , len_lblk , ret );
4742+ return ret ;
4743+ }
4744+
46934745/*
46944746 * preallocate space for a file. This implements ext4's fallocate file
46954747 * operation, which gets called from sys_fallocate system call.
@@ -4700,12 +4752,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
47004752long ext4_fallocate (struct file * file , int mode , loff_t offset , loff_t len )
47014753{
47024754 struct inode * inode = file_inode (file );
4703- loff_t new_size = 0 ;
4704- unsigned int max_blocks ;
4705- int ret = 0 ;
4706- int flags ;
4707- ext4_lblk_t lblk ;
4708- unsigned int blkbits = inode -> i_blkbits ;
4755+ int ret ;
47094756
47104757 /*
47114758 * Encrypted inodes can't handle collapse range or insert
@@ -4727,71 +4774,19 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47274774 ret = ext4_convert_inline_data (inode );
47284775 inode_unlock (inode );
47294776 if (ret )
4730- goto exit ;
4777+ return ret ;
47314778
4732- if (mode & FALLOC_FL_PUNCH_HOLE ) {
4779+ if (mode & FALLOC_FL_PUNCH_HOLE )
47334780 ret = ext4_punch_hole (file , offset , len );
4734- goto exit ;
4735- }
4736-
4737- if (mode & FALLOC_FL_COLLAPSE_RANGE ) {
4781+ else if (mode & FALLOC_FL_COLLAPSE_RANGE )
47384782 ret = ext4_collapse_range (file , offset , len );
4739- goto exit ;
4740- }
4741-
4742- if (mode & FALLOC_FL_INSERT_RANGE ) {
4783+ else if (mode & FALLOC_FL_INSERT_RANGE )
47434784 ret = ext4_insert_range (file , offset , len );
4744- goto exit ;
4745- }
4746-
4747- if (mode & FALLOC_FL_ZERO_RANGE ) {
4785+ else if (mode & FALLOC_FL_ZERO_RANGE )
47484786 ret = ext4_zero_range (file , offset , len , mode );
4749- goto exit ;
4750- }
4751- trace_ext4_fallocate_enter (inode , offset , len , mode );
4752- lblk = offset >> blkbits ;
4753-
4754- max_blocks = EXT4_MAX_BLOCKS (len , offset , blkbits );
4755- flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT ;
4756-
4757- inode_lock (inode );
4758-
4759- /*
4760- * We only support preallocation for extent-based files only
4761- */
4762- if (!(ext4_test_inode_flag (inode , EXT4_INODE_EXTENTS ))) {
4763- ret = - EOPNOTSUPP ;
4764- goto out ;
4765- }
4766-
4767- if (!(mode & FALLOC_FL_KEEP_SIZE ) &&
4768- (offset + len > inode -> i_size ||
4769- offset + len > EXT4_I (inode )-> i_disksize )) {
4770- new_size = offset + len ;
4771- ret = inode_newsize_ok (inode , new_size );
4772- if (ret )
4773- goto out ;
4774- }
4775-
4776- /* Wait all existing dio workers, newcomers will block on i_rwsem */
4777- inode_dio_wait (inode );
4778-
4779- ret = file_modified (file );
4780- if (ret )
4781- goto out ;
4782-
4783- ret = ext4_alloc_file_blocks (file , lblk , max_blocks , new_size , flags );
4784- if (ret )
4785- goto out ;
4787+ else
4788+ ret = ext4_do_fallocate (file , offset , len , mode );
47864789
4787- if (file -> f_flags & O_SYNC && EXT4_SB (inode -> i_sb )-> s_journal ) {
4788- ret = ext4_fc_commit (EXT4_SB (inode -> i_sb )-> s_journal ,
4789- EXT4_I (inode )-> i_sync_tid );
4790- }
4791- out :
4792- inode_unlock (inode );
4793- trace_ext4_fallocate_exit (inode , offset , max_blocks , ret );
4794- exit :
47954790 return ret ;
47964791}
47974792
0 commit comments