@@ -2044,12 +2044,23 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
2044
2044
}
2045
2045
2046
2046
/*
2047
+ * ext4_ext_in_cache()
2048
+ * Checks to see if the given block is in the cache.
2049
+ * If it is, the cached extent is stored in the given
2050
+ * cache extent pointer. If the cached extent is a hole,
2051
+ * this routine should be used instead of
2052
+ * ext4_ext_in_cache if the calling function needs to
2053
+ * know the size of the hole.
2054
+ *
2055
+ * @inode: The files inode
2056
+ * @block: The block to look for in the cache
2057
+ * @ex: Pointer where the cached extent will be stored
2058
+ * if it contains block
2059
+ *
2047
2060
* Return 0 if cache is invalid; 1 if the cache is valid
2048
2061
*/
2049
- static int
2050
- ext4_ext_in_cache (struct inode * inode , ext4_lblk_t block ,
2051
- struct ext4_extent * ex )
2052
- {
2062
+ static int ext4_ext_check_cache (struct inode * inode , ext4_lblk_t block ,
2063
+ struct ext4_ext_cache * ex ){
2053
2064
struct ext4_ext_cache * cex ;
2054
2065
struct ext4_sb_info * sbi ;
2055
2066
int ret = 0 ;
@@ -2066,9 +2077,7 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
2066
2077
goto errout ;
2067
2078
2068
2079
if (in_range (block , cex -> ec_block , cex -> ec_len )) {
2069
- ex -> ee_block = cpu_to_le32 (cex -> ec_block );
2070
- ext4_ext_store_pblock (ex , cex -> ec_start );
2071
- ex -> ee_len = cpu_to_le16 (cex -> ec_len );
2080
+ memcpy (ex , cex , sizeof (struct ext4_ext_cache ));
2072
2081
ext_debug ("%u cached by %u:%u:%llu\n" ,
2073
2082
block ,
2074
2083
cex -> ec_block , cex -> ec_len , cex -> ec_start );
@@ -2083,6 +2092,37 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
2083
2092
return ret ;
2084
2093
}
2085
2094
2095
+ /*
2096
+ * ext4_ext_in_cache()
2097
+ * Checks to see if the given block is in the cache.
2098
+ * If it is, the cached extent is stored in the given
2099
+ * extent pointer.
2100
+ *
2101
+ * @inode: The files inode
2102
+ * @block: The block to look for in the cache
2103
+ * @ex: Pointer where the cached extent will be stored
2104
+ * if it contains block
2105
+ *
2106
+ * Return 0 if cache is invalid; 1 if the cache is valid
2107
+ */
2108
+ static int
2109
+ ext4_ext_in_cache (struct inode * inode , ext4_lblk_t block ,
2110
+ struct ext4_extent * ex )
2111
+ {
2112
+ struct ext4_ext_cache cex ;
2113
+ int ret = 0 ;
2114
+
2115
+ if (ext4_ext_check_cache (inode , block , & cex )) {
2116
+ ex -> ee_block = cpu_to_le32 (cex .ec_block );
2117
+ ext4_ext_store_pblock (ex , cex .ec_start );
2118
+ ex -> ee_len = cpu_to_le16 (cex .ec_len );
2119
+ ret = 1 ;
2120
+ }
2121
+
2122
+ return ret ;
2123
+ }
2124
+
2125
+
2086
2126
/*
2087
2127
* ext4_ext_rm_idx:
2088
2128
* removes index from the index block.
@@ -3724,17 +3764,20 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
3724
3764
struct ext4_map_blocks map ;
3725
3765
unsigned int credits , blkbits = inode -> i_blkbits ;
3726
3766
3727
- /* We only support the FALLOC_FL_KEEP_SIZE mode */
3728
- if (mode & ~FALLOC_FL_KEEP_SIZE )
3729
- return - EOPNOTSUPP ;
3730
-
3731
3767
/*
3732
3768
* currently supporting (pre)allocate mode for extent-based
3733
3769
* files _only_
3734
3770
*/
3735
3771
if (!(ext4_test_inode_flag (inode , EXT4_INODE_EXTENTS )))
3736
3772
return - EOPNOTSUPP ;
3737
3773
3774
+ /* Return error if mode is not supported */
3775
+ if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE ))
3776
+ return - EOPNOTSUPP ;
3777
+
3778
+ if (mode & FALLOC_FL_PUNCH_HOLE )
3779
+ return ext4_punch_hole (file , offset , len );
3780
+
3738
3781
trace_ext4_fallocate_enter (inode , offset , len , mode );
3739
3782
map .m_lblk = offset >> blkbits ;
3740
3783
/*
@@ -4100,6 +4143,177 @@ static int ext4_xattr_fiemap(struct inode *inode,
4100
4143
return (error < 0 ? error : 0 );
4101
4144
}
4102
4145
4146
+ /*
4147
+ * ext4_ext_punch_hole
4148
+ *
4149
+ * Punches a hole of "length" bytes in a file starting
4150
+ * at byte "offset"
4151
+ *
4152
+ * @inode: The inode of the file to punch a hole in
4153
+ * @offset: The starting byte offset of the hole
4154
+ * @length: The length of the hole
4155
+ *
4156
+ * Returns the number of blocks removed or negative on err
4157
+ */
4158
+ int ext4_ext_punch_hole (struct file * file , loff_t offset , loff_t length )
4159
+ {
4160
+ struct inode * inode = file -> f_path .dentry -> d_inode ;
4161
+ struct super_block * sb = inode -> i_sb ;
4162
+ struct ext4_ext_cache cache_ex ;
4163
+ ext4_lblk_t first_block , last_block , num_blocks , iblock , max_blocks ;
4164
+ struct address_space * mapping = inode -> i_mapping ;
4165
+ struct ext4_map_blocks map ;
4166
+ handle_t * handle ;
4167
+ loff_t first_block_offset , last_block_offset , block_len ;
4168
+ loff_t first_page , last_page , first_page_offset , last_page_offset ;
4169
+ int ret , credits , blocks_released , err = 0 ;
4170
+
4171
+ first_block = (offset + sb -> s_blocksize - 1 ) >>
4172
+ EXT4_BLOCK_SIZE_BITS (sb );
4173
+ last_block = (offset + length ) >> EXT4_BLOCK_SIZE_BITS (sb );
4174
+
4175
+ first_block_offset = first_block << EXT4_BLOCK_SIZE_BITS (sb );
4176
+ last_block_offset = last_block << EXT4_BLOCK_SIZE_BITS (sb );
4177
+
4178
+ first_page = (offset + PAGE_CACHE_SIZE - 1 ) >> PAGE_CACHE_SHIFT ;
4179
+ last_page = (offset + length ) >> PAGE_CACHE_SHIFT ;
4180
+
4181
+ first_page_offset = first_page << PAGE_CACHE_SHIFT ;
4182
+ last_page_offset = last_page << PAGE_CACHE_SHIFT ;
4183
+
4184
+ /*
4185
+ * Write out all dirty pages to avoid race conditions
4186
+ * Then release them.
4187
+ */
4188
+ if (mapping -> nrpages && mapping_tagged (mapping , PAGECACHE_TAG_DIRTY )) {
4189
+ err = filemap_write_and_wait_range (mapping ,
4190
+ first_page_offset == 0 ? 0 : first_page_offset - 1 ,
4191
+ last_page_offset );
4192
+
4193
+ if (err )
4194
+ return err ;
4195
+ }
4196
+
4197
+ /* Now release the pages */
4198
+ if (last_page_offset > first_page_offset ) {
4199
+ truncate_inode_pages_range (mapping , first_page_offset ,
4200
+ last_page_offset - 1 );
4201
+ }
4202
+
4203
+ /* finish any pending end_io work */
4204
+ ext4_flush_completed_IO (inode );
4205
+
4206
+ credits = ext4_writepage_trans_blocks (inode );
4207
+ handle = ext4_journal_start (inode , credits );
4208
+ if (IS_ERR (handle ))
4209
+ return PTR_ERR (handle );
4210
+
4211
+ err = ext4_orphan_add (handle , inode );
4212
+ if (err )
4213
+ goto out ;
4214
+
4215
+ /*
4216
+ * Now we need to zero out the un block aligned data.
4217
+ * If the file is smaller than a block, just
4218
+ * zero out the middle
4219
+ */
4220
+ if (first_block > last_block )
4221
+ ext4_block_zero_page_range (handle , mapping , offset , length );
4222
+ else {
4223
+ /* zero out the head of the hole before the first block */
4224
+ block_len = first_block_offset - offset ;
4225
+ if (block_len > 0 )
4226
+ ext4_block_zero_page_range (handle , mapping ,
4227
+ offset , block_len );
4228
+
4229
+ /* zero out the tail of the hole after the last block */
4230
+ block_len = offset + length - last_block_offset ;
4231
+ if (block_len > 0 ) {
4232
+ ext4_block_zero_page_range (handle , mapping ,
4233
+ last_block_offset , block_len );
4234
+ }
4235
+ }
4236
+
4237
+ /* If there are no blocks to remove, return now */
4238
+ if (first_block >= last_block )
4239
+ goto out ;
4240
+
4241
+ down_write (& EXT4_I (inode )-> i_data_sem );
4242
+ ext4_ext_invalidate_cache (inode );
4243
+ ext4_discard_preallocations (inode );
4244
+
4245
+ /*
4246
+ * Loop over all the blocks and identify blocks
4247
+ * that need to be punched out
4248
+ */
4249
+ iblock = first_block ;
4250
+ blocks_released = 0 ;
4251
+ while (iblock < last_block ) {
4252
+ max_blocks = last_block - iblock ;
4253
+ num_blocks = 1 ;
4254
+ memset (& map , 0 , sizeof (map ));
4255
+ map .m_lblk = iblock ;
4256
+ map .m_len = max_blocks ;
4257
+ ret = ext4_ext_map_blocks (handle , inode , & map ,
4258
+ EXT4_GET_BLOCKS_PUNCH_OUT_EXT );
4259
+
4260
+ if (ret > 0 ) {
4261
+ blocks_released += ret ;
4262
+ num_blocks = ret ;
4263
+ } else if (ret == 0 ) {
4264
+ /*
4265
+ * If map blocks could not find the block,
4266
+ * then it is in a hole. If the hole was
4267
+ * not already cached, then map blocks should
4268
+ * put it in the cache. So we can get the hole
4269
+ * out of the cache
4270
+ */
4271
+ memset (& cache_ex , 0 , sizeof (cache_ex ));
4272
+ if ((ext4_ext_check_cache (inode , iblock , & cache_ex )) &&
4273
+ !cache_ex .ec_start ) {
4274
+
4275
+ /* The hole is cached */
4276
+ num_blocks = cache_ex .ec_block +
4277
+ cache_ex .ec_len - iblock ;
4278
+
4279
+ } else {
4280
+ /* The block could not be identified */
4281
+ err = - EIO ;
4282
+ break ;
4283
+ }
4284
+ } else {
4285
+ /* Map blocks error */
4286
+ err = ret ;
4287
+ break ;
4288
+ }
4289
+
4290
+ if (num_blocks == 0 ) {
4291
+ /* This condition should never happen */
4292
+ ext_debug ("Block lookup failed" );
4293
+ err = - EIO ;
4294
+ break ;
4295
+ }
4296
+
4297
+ iblock += num_blocks ;
4298
+ }
4299
+
4300
+ if (blocks_released > 0 ) {
4301
+ ext4_ext_invalidate_cache (inode );
4302
+ ext4_discard_preallocations (inode );
4303
+ }
4304
+
4305
+ if (IS_SYNC (inode ))
4306
+ ext4_handle_sync (handle );
4307
+
4308
+ up_write (& EXT4_I (inode )-> i_data_sem );
4309
+
4310
+ out :
4311
+ ext4_orphan_del (handle , inode );
4312
+ inode -> i_mtime = inode -> i_ctime = ext4_current_time (inode );
4313
+ ext4_mark_inode_dirty (handle , inode );
4314
+ ext4_journal_stop (handle );
4315
+ return err ;
4316
+ }
4103
4317
int ext4_fiemap (struct inode * inode , struct fiemap_extent_info * fieinfo ,
4104
4318
__u64 start , __u64 len )
4105
4319
{
0 commit comments