aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c109
1 files changed, 76 insertions, 33 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 82df3ce9874a..01b0c208f625 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3313,6 +3313,11 @@ static int ext4_split_extent(handle_t *handle,
3313 return PTR_ERR(path); 3313 return PTR_ERR(path);
3314 depth = ext_depth(inode); 3314 depth = ext_depth(inode);
3315 ex = path[depth].p_ext; 3315 ex = path[depth].p_ext;
3316 if (!ex) {
3317 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
3318 (unsigned long) map->m_lblk);
3319 return -EIO;
3320 }
3316 uninitialized = ext4_ext_is_uninitialized(ex); 3321 uninitialized = ext4_ext_is_uninitialized(ex);
3317 split_flag1 = 0; 3322 split_flag1 = 0;
3318 3323
@@ -3694,6 +3699,12 @@ static int ext4_convert_initialized_extents(handle_t *handle,
3694 } 3699 }
3695 depth = ext_depth(inode); 3700 depth = ext_depth(inode);
3696 ex = path[depth].p_ext; 3701 ex = path[depth].p_ext;
3702 if (!ex) {
3703 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
3704 (unsigned long) map->m_lblk);
3705 err = -EIO;
3706 goto out;
3707 }
3697 } 3708 }
3698 3709
3699 err = ext4_ext_get_access(handle, inode, path + depth); 3710 err = ext4_ext_get_access(handle, inode, path + depth);
@@ -4730,6 +4741,9 @@ static long ext4_zero_range(struct file *file, loff_t offset,
4730 4741
4731 trace_ext4_zero_range(inode, offset, len, mode); 4742 trace_ext4_zero_range(inode, offset, len, mode);
4732 4743
4744 if (!S_ISREG(inode->i_mode))
4745 return -EINVAL;
4746
4733 /* 4747 /*
4734 * Write out all dirty pages to avoid race conditions 4748 * Write out all dirty pages to avoid race conditions
4735 * Then release them. 4749 * Then release them.
@@ -4878,9 +4892,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4878 if (mode & FALLOC_FL_PUNCH_HOLE) 4892 if (mode & FALLOC_FL_PUNCH_HOLE)
4879 return ext4_punch_hole(inode, offset, len); 4893 return ext4_punch_hole(inode, offset, len);
4880 4894
4881 if (mode & FALLOC_FL_COLLAPSE_RANGE)
4882 return ext4_collapse_range(inode, offset, len);
4883
4884 ret = ext4_convert_inline_data(inode); 4895 ret = ext4_convert_inline_data(inode);
4885 if (ret) 4896 if (ret)
4886 return ret; 4897 return ret;
@@ -4892,6 +4903,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4892 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) 4903 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
4893 return -EOPNOTSUPP; 4904 return -EOPNOTSUPP;
4894 4905
4906 if (mode & FALLOC_FL_COLLAPSE_RANGE)
4907 return ext4_collapse_range(inode, offset, len);
4908
4895 if (mode & FALLOC_FL_ZERO_RANGE) 4909 if (mode & FALLOC_FL_ZERO_RANGE)
4896 return ext4_zero_range(file, offset, len, mode); 4910 return ext4_zero_range(file, offset, len, mode);
4897 4911
@@ -5229,18 +5243,19 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
5229 if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr)) 5243 if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr))
5230 update = 1; 5244 update = 1;
5231 5245
5232 *start = ex_last->ee_block + 5246 *start = le32_to_cpu(ex_last->ee_block) +
5233 ext4_ext_get_actual_len(ex_last); 5247 ext4_ext_get_actual_len(ex_last);
5234 5248
5235 while (ex_start <= ex_last) { 5249 while (ex_start <= ex_last) {
5236 ex_start->ee_block -= shift; 5250 le32_add_cpu(&ex_start->ee_block, -shift);
5237 if (ex_start > 5251 /* Try to merge to the left. */
5238 EXT_FIRST_EXTENT(path[depth].p_hdr)) { 5252 if ((ex_start >
5239 if (ext4_ext_try_to_merge_right(inode, 5253 EXT_FIRST_EXTENT(path[depth].p_hdr)) &&
5240 path, ex_start - 1)) 5254 ext4_ext_try_to_merge_right(inode,
5241 ex_last--; 5255 path, ex_start - 1))
5242 } 5256 ex_last--;
5243 ex_start++; 5257 else
5258 ex_start++;
5244 } 5259 }
5245 err = ext4_ext_dirty(handle, inode, path + depth); 5260 err = ext4_ext_dirty(handle, inode, path + depth);
5246 if (err) 5261 if (err)
@@ -5255,7 +5270,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
5255 if (err) 5270 if (err)
5256 goto out; 5271 goto out;
5257 5272
5258 path[depth].p_idx->ei_block -= shift; 5273 le32_add_cpu(&path[depth].p_idx->ei_block, -shift);
5259 err = ext4_ext_dirty(handle, inode, path + depth); 5274 err = ext4_ext_dirty(handle, inode, path + depth);
5260 if (err) 5275 if (err)
5261 goto out; 5276 goto out;
@@ -5300,7 +5315,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
5300 return ret; 5315 return ret;
5301 } 5316 }
5302 5317
5303 stop_block = extent->ee_block + ext4_ext_get_actual_len(extent); 5318 stop_block = le32_to_cpu(extent->ee_block) +
5319 ext4_ext_get_actual_len(extent);
5304 ext4_ext_drop_refs(path); 5320 ext4_ext_drop_refs(path);
5305 kfree(path); 5321 kfree(path);
5306 5322
@@ -5313,10 +5329,18 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
5313 * enough to accomodate the shift. 5329 * enough to accomodate the shift.
5314 */ 5330 */
5315 path = ext4_ext_find_extent(inode, start - 1, NULL, 0); 5331 path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
5332 if (IS_ERR(path))
5333 return PTR_ERR(path);
5316 depth = path->p_depth; 5334 depth = path->p_depth;
5317 extent = path[depth].p_ext; 5335 extent = path[depth].p_ext;
5318 ex_start = extent->ee_block; 5336 if (extent) {
5319 ex_end = extent->ee_block + ext4_ext_get_actual_len(extent); 5337 ex_start = le32_to_cpu(extent->ee_block);
5338 ex_end = le32_to_cpu(extent->ee_block) +
5339 ext4_ext_get_actual_len(extent);
5340 } else {
5341 ex_start = 0;
5342 ex_end = 0;
5343 }
5320 ext4_ext_drop_refs(path); 5344 ext4_ext_drop_refs(path);
5321 kfree(path); 5345 kfree(path);
5322 5346
@@ -5331,7 +5355,13 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
5331 return PTR_ERR(path); 5355 return PTR_ERR(path);
5332 depth = path->p_depth; 5356 depth = path->p_depth;
5333 extent = path[depth].p_ext; 5357 extent = path[depth].p_ext;
5334 current_block = extent->ee_block; 5358 if (!extent) {
5359 EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
5360 (unsigned long) start);
5361 return -EIO;
5362 }
5363
5364 current_block = le32_to_cpu(extent->ee_block);
5335 if (start > current_block) { 5365 if (start > current_block) {
5336 /* Hole, move to the next extent */ 5366 /* Hole, move to the next extent */
5337 ret = mext_next_extent(inode, path, &extent); 5367 ret = mext_next_extent(inode, path, &extent);
@@ -5365,17 +5395,18 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5365 ext4_lblk_t punch_start, punch_stop; 5395 ext4_lblk_t punch_start, punch_stop;
5366 handle_t *handle; 5396 handle_t *handle;
5367 unsigned int credits; 5397 unsigned int credits;
5368 loff_t new_size; 5398 loff_t new_size, ioffset;
5369 int ret; 5399 int ret;
5370 5400
5371 BUG_ON(offset + len > i_size_read(inode));
5372
5373 /* Collapse range works only on fs block size aligned offsets. */ 5401 /* Collapse range works only on fs block size aligned offsets. */
5374 if (offset & (EXT4_BLOCK_SIZE(sb) - 1) || 5402 if (offset & (EXT4_BLOCK_SIZE(sb) - 1) ||
5375 len & (EXT4_BLOCK_SIZE(sb) - 1)) 5403 len & (EXT4_BLOCK_SIZE(sb) - 1))
5376 return -EINVAL; 5404 return -EINVAL;
5377 5405
5378 if (!S_ISREG(inode->i_mode)) 5406 if (!S_ISREG(inode->i_mode))
5407 return -EINVAL;
5408
5409 if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1)
5379 return -EOPNOTSUPP; 5410 return -EOPNOTSUPP;
5380 5411
5381 trace_ext4_collapse_range(inode, offset, len); 5412 trace_ext4_collapse_range(inode, offset, len);
@@ -5383,22 +5414,34 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5383 punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb); 5414 punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb);
5384 punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb); 5415 punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb);
5385 5416
5417 /* Call ext4_force_commit to flush all data in case of data=journal. */
5418 if (ext4_should_journal_data(inode)) {
5419 ret = ext4_force_commit(inode->i_sb);
5420 if (ret)
5421 return ret;
5422 }
5423
5424 /*
5425 * Need to round down offset to be aligned with page size boundary
5426 * for page size > block size.
5427 */
5428 ioffset = round_down(offset, PAGE_SIZE);
5429
5386 /* Write out all dirty pages */ 5430 /* Write out all dirty pages */
5387 ret = filemap_write_and_wait_range(inode->i_mapping, offset, -1); 5431 ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
5432 LLONG_MAX);
5388 if (ret) 5433 if (ret)
5389 return ret; 5434 return ret;
5390 5435
5391 /* Take mutex lock */ 5436 /* Take mutex lock */
5392 mutex_lock(&inode->i_mutex); 5437 mutex_lock(&inode->i_mutex);
5393 5438
5394 /* It's not possible punch hole on append only file */ 5439 /*
5395 if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { 5440 * There is no need to overlap collapse range with EOF, in which case
5396 ret = -EPERM; 5441 * it is effectively a truncate operation
5397 goto out_mutex; 5442 */
5398 } 5443 if (offset + len >= i_size_read(inode)) {
5399 5444 ret = -EINVAL;
5400 if (IS_SWAPFILE(inode)) {
5401 ret = -ETXTBSY;
5402 goto out_mutex; 5445 goto out_mutex;
5403 } 5446 }
5404 5447
@@ -5408,7 +5451,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5408 goto out_mutex; 5451 goto out_mutex;
5409 } 5452 }
5410 5453
5411 truncate_pagecache_range(inode, offset, -1); 5454 truncate_pagecache(inode, ioffset);
5412 5455
5413 /* Wait for existing dio to complete */ 5456 /* Wait for existing dio to complete */
5414 ext4_inode_block_unlocked_dio(inode); 5457 ext4_inode_block_unlocked_dio(inode);
@@ -5425,7 +5468,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5425 ext4_discard_preallocations(inode); 5468 ext4_discard_preallocations(inode);
5426 5469
5427 ret = ext4_es_remove_extent(inode, punch_start, 5470 ret = ext4_es_remove_extent(inode, punch_start,
5428 EXT_MAX_BLOCKS - punch_start - 1); 5471 EXT_MAX_BLOCKS - punch_start);
5429 if (ret) { 5472 if (ret) {
5430 up_write(&EXT4_I(inode)->i_data_sem); 5473 up_write(&EXT4_I(inode)->i_data_sem);
5431 goto out_stop; 5474 goto out_stop;
@@ -5436,6 +5479,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5436 up_write(&EXT4_I(inode)->i_data_sem); 5479 up_write(&EXT4_I(inode)->i_data_sem);
5437 goto out_stop; 5480 goto out_stop;
5438 } 5481 }
5482 ext4_discard_preallocations(inode);
5439 5483
5440 ret = ext4_ext_shift_extents(inode, handle, punch_stop, 5484 ret = ext4_ext_shift_extents(inode, handle, punch_stop,
5441 punch_stop - punch_start); 5485 punch_stop - punch_start);
@@ -5445,10 +5489,9 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5445 } 5489 }
5446 5490
5447 new_size = i_size_read(inode) - len; 5491 new_size = i_size_read(inode) - len;
5448 truncate_setsize(inode, new_size); 5492 i_size_write(inode, new_size);
5449 EXT4_I(inode)->i_disksize = new_size; 5493 EXT4_I(inode)->i_disksize = new_size;
5450 5494
5451 ext4_discard_preallocations(inode);
5452 up_write(&EXT4_I(inode)->i_data_sem); 5495 up_write(&EXT4_I(inode)->i_data_sem);
5453 if (IS_SYNC(inode)) 5496 if (IS_SYNC(inode))
5454 ext4_handle_sync(handle); 5497 ext4_handle_sync(handle);