@@ -4546,6 +4546,64 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
4546
4546
ext4_std_error (inode -> i_sb , err );
4547
4547
}
4548
4548
4549
+ static int ext4_alloc_file_blocks (struct file * file , ext4_lblk_t offset ,
4550
+ ext4_lblk_t len , int flags , int mode )
4551
+ {
4552
+ struct inode * inode = file_inode (file );
4553
+ handle_t * handle ;
4554
+ int ret = 0 ;
4555
+ int ret2 = 0 ;
4556
+ int retries = 0 ;
4557
+ struct ext4_map_blocks map ;
4558
+ unsigned int credits ;
4559
+
4560
+ map .m_lblk = offset ;
4561
+ /*
4562
+ * Don't normalize the request if it can fit in one extent so
4563
+ * that it doesn't get unnecessarily split into multiple
4564
+ * extents.
4565
+ */
4566
+ if (len <= EXT_UNINIT_MAX_LEN )
4567
+ flags |= EXT4_GET_BLOCKS_NO_NORMALIZE ;
4568
+
4569
+ /*
4570
+ * credits to insert 1 extent into extent tree
4571
+ */
4572
+ credits = ext4_chunk_trans_blocks (inode , len );
4573
+
4574
+ retry :
4575
+ while (ret >= 0 && ret < len ) {
4576
+ map .m_lblk = map .m_lblk + ret ;
4577
+ map .m_len = len = len - ret ;
4578
+ handle = ext4_journal_start (inode , EXT4_HT_MAP_BLOCKS ,
4579
+ credits );
4580
+ if (IS_ERR (handle )) {
4581
+ ret = PTR_ERR (handle );
4582
+ break ;
4583
+ }
4584
+ ret = ext4_map_blocks (handle , inode , & map , flags );
4585
+ if (ret <= 0 ) {
4586
+ ext4_debug ("inode #%lu: block %u: len %u: "
4587
+ "ext4_ext_map_blocks returned %d" ,
4588
+ inode -> i_ino , map .m_lblk ,
4589
+ map .m_len , ret );
4590
+ ext4_mark_inode_dirty (handle , inode );
4591
+ ret2 = ext4_journal_stop (handle );
4592
+ break ;
4593
+ }
4594
+ ret2 = ext4_journal_stop (handle );
4595
+ if (ret2 )
4596
+ break ;
4597
+ }
4598
+ if (ret == - ENOSPC &&
4599
+ ext4_should_retry_alloc (inode -> i_sb , & retries )) {
4600
+ ret = 0 ;
4601
+ goto retry ;
4602
+ }
4603
+
4604
+ return ret > 0 ? ret2 : ret ;
4605
+ }
4606
+
4549
4607
/*
4550
4608
* preallocate space for a file. This implements ext4's fallocate file
4551
4609
* operation, which gets called from sys_fallocate system call.
@@ -4560,12 +4618,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4560
4618
loff_t new_size = 0 ;
4561
4619
unsigned int max_blocks ;
4562
4620
int ret = 0 ;
4563
- int ret2 = 0 ;
4564
- int retries = 0 ;
4565
4621
int flags ;
4566
- struct ext4_map_blocks map ;
4622
+ ext4_lblk_t lblk ;
4567
4623
struct timespec tv ;
4568
- unsigned int credits , blkbits = inode -> i_blkbits ;
4624
+ unsigned int blkbits = inode -> i_blkbits ;
4569
4625
4570
4626
/* Return error if mode is not supported */
4571
4627
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
@@ -4590,17 +4646,18 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4590
4646
return - EOPNOTSUPP ;
4591
4647
4592
4648
trace_ext4_fallocate_enter (inode , offset , len , mode );
4593
- map . m_lblk = offset >> blkbits ;
4649
+ lblk = offset >> blkbits ;
4594
4650
/*
4595
4651
* We can't just convert len to max_blocks because
4596
4652
* If blocksize = 4096 offset = 3072 and len = 2048
4597
4653
*/
4598
4654
max_blocks = (EXT4_BLOCK_ALIGN (len + offset , blkbits ) >> blkbits )
4599
- - map .m_lblk ;
4600
- /*
4601
- * credits to insert 1 extent into extent tree
4602
- */
4603
- credits = ext4_chunk_trans_blocks (inode , max_blocks );
4655
+ - lblk ;
4656
+
4657
+ flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT ;
4658
+ if (mode & FALLOC_FL_KEEP_SIZE )
4659
+ flags |= EXT4_GET_BLOCKS_KEEP_SIZE ;
4660
+
4604
4661
mutex_lock (& inode -> i_mutex );
4605
4662
4606
4663
if (!(mode & FALLOC_FL_KEEP_SIZE ) &&
@@ -4611,61 +4668,24 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4611
4668
goto out ;
4612
4669
}
4613
4670
4614
- flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT ;
4615
- if (mode & FALLOC_FL_KEEP_SIZE )
4616
- flags |= EXT4_GET_BLOCKS_KEEP_SIZE ;
4617
- /*
4618
- * Don't normalize the request if it can fit in one extent so
4619
- * that it doesn't get unnecessarily split into multiple
4620
- * extents.
4621
- */
4622
- if (len <= EXT_UNINIT_MAX_LEN << blkbits )
4623
- flags |= EXT4_GET_BLOCKS_NO_NORMALIZE ;
4624
-
4625
- retry :
4626
- while (ret >= 0 && ret < max_blocks ) {
4627
- map .m_lblk = map .m_lblk + ret ;
4628
- map .m_len = max_blocks = max_blocks - ret ;
4629
- handle = ext4_journal_start (inode , EXT4_HT_MAP_BLOCKS ,
4630
- credits );
4631
- if (IS_ERR (handle )) {
4632
- ret = PTR_ERR (handle );
4633
- break ;
4634
- }
4635
- ret = ext4_map_blocks (handle , inode , & map , flags );
4636
- if (ret <= 0 ) {
4637
- ext4_debug ("inode #%lu: block %u: len %u: "
4638
- "ext4_ext_map_blocks returned %d" ,
4639
- inode -> i_ino , map .m_lblk ,
4640
- map .m_len , ret );
4641
- ext4_mark_inode_dirty (handle , inode );
4642
- ret2 = ext4_journal_stop (handle );
4643
- break ;
4644
- }
4645
- ret2 = ext4_journal_stop (handle );
4646
- if (ret2 )
4647
- break ;
4648
- }
4649
- if (ret == - ENOSPC &&
4650
- ext4_should_retry_alloc (inode -> i_sb , & retries )) {
4651
- ret = 0 ;
4652
- goto retry ;
4653
- }
4671
+ ret = ext4_alloc_file_blocks (file , lblk , max_blocks , flags , mode );
4672
+ if (ret )
4673
+ goto out ;
4654
4674
4655
4675
handle = ext4_journal_start (inode , EXT4_HT_INODE , 2 );
4656
4676
if (IS_ERR (handle ))
4657
4677
goto out ;
4658
4678
4659
4679
tv = inode -> i_ctime = ext4_current_time (inode );
4660
4680
4661
- if (ret > 0 && new_size ) {
4681
+ if (! ret && new_size ) {
4662
4682
if (new_size > i_size_read (inode )) {
4663
4683
i_size_write (inode , new_size );
4664
4684
inode -> i_mtime = tv ;
4665
4685
}
4666
4686
if (new_size > EXT4_I (inode )-> i_disksize )
4667
4687
ext4_update_i_disksize (inode , new_size );
4668
- } else if (ret > 0 && !new_size ) {
4688
+ } else if (! ret && !new_size ) {
4669
4689
/*
4670
4690
* Mark that we allocate beyond EOF so the subsequent truncate
4671
4691
* can proceed even if the new size is the same as i_size.
@@ -4680,9 +4700,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4680
4700
ext4_journal_stop (handle );
4681
4701
out :
4682
4702
mutex_unlock (& inode -> i_mutex );
4683
- trace_ext4_fallocate_exit (inode , offset , max_blocks ,
4684
- ret > 0 ? ret2 : ret );
4685
- return ret > 0 ? ret2 : ret ;
4703
+ trace_ext4_fallocate_exit (inode , offset , max_blocks , ret );
4704
+ return ret ;
4686
4705
}
4687
4706
4688
4707
/*
0 commit comments