diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-28 00:36:39 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-28 00:36:39 -0400 |
commit | d35cc56ddfc948d8df1aa6d41ac345fcec01854d (patch) | |
tree | 7e23a0e3dde639236e019aa88309d919941958e5 /fs/ext4/extents.c | |
parent | 86d56134f1b67d0c18025ba5cade95c048ed528d (diff) | |
parent | d1db0eea852497762cab43b905b879dfcd3b8987 (diff) |
Merge 3.15-rc3 into staging-next
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 109 |
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); |