aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2014-03-18 18:03:51 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-03-18 18:03:51 -0400
commit0e8b6879f3c234036181526683be2b0231892ae4 (patch)
tree7fcff688fec8a0da538938830c5ea3cf8964f28f /fs/ext4
parentf282ac19d86f0507e91759dcf3d15fcb3a964d2a (diff)
ext4: refactor ext4_fallocate code
Move block allocation out of the ext4_fallocate into separate function called ext4_alloc_file_blocks(). This will allow us to use the same allocation code for other allocation operations such as zero range which is commit in the next patch. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/extents.c129
1 files changed, 74 insertions, 55 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e4be6b79121d..2db2d77769a2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4546,6 +4546,64 @@ retry:
4546 ext4_std_error(inode->i_sb, err); 4546 ext4_std_error(inode->i_sb, err);
4547} 4547}
4548 4548
4549static 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
4574retry:
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 * preallocate space for a file. This implements ext4's fallocate file 4608 * preallocate space for a file. This implements ext4's fallocate file
4551 * operation, which gets called from sys_fallocate system call. 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 loff_t new_size = 0; 4618 loff_t new_size = 0;
4561 unsigned int max_blocks; 4619 unsigned int max_blocks;
4562 int ret = 0; 4620 int ret = 0;
4563 int ret2 = 0;
4564 int retries = 0;
4565 int flags; 4621 int flags;
4566 struct ext4_map_blocks map; 4622 ext4_lblk_t lblk;
4567 struct timespec tv; 4623 struct timespec tv;
4568 unsigned int credits, blkbits = inode->i_blkbits; 4624 unsigned int blkbits = inode->i_blkbits;
4569 4625
4570 /* Return error if mode is not supported */ 4626 /* Return error if mode is not supported */
4571 if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | 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 return -EOPNOTSUPP; 4646 return -EOPNOTSUPP;
4591 4647
4592 trace_ext4_fallocate_enter(inode, offset, len, mode); 4648 trace_ext4_fallocate_enter(inode, offset, len, mode);
4593 map.m_lblk = offset >> blkbits; 4649 lblk = offset >> blkbits;
4594 /* 4650 /*
4595 * We can't just convert len to max_blocks because 4651 * We can't just convert len to max_blocks because
4596 * If blocksize = 4096 offset = 3072 and len = 2048 4652 * If blocksize = 4096 offset = 3072 and len = 2048
4597 */ 4653 */
4598 max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) 4654 max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
4599 - map.m_lblk; 4655 - lblk;
4600 /* 4656
4601 * credits to insert 1 extent into extent tree 4657 flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT;
4602 */ 4658 if (mode & FALLOC_FL_KEEP_SIZE)
4603 credits = ext4_chunk_trans_blocks(inode, max_blocks); 4659 flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
4660
4604 mutex_lock(&inode->i_mutex); 4661 mutex_lock(&inode->i_mutex);
4605 4662
4606 if (!(mode & FALLOC_FL_KEEP_SIZE) && 4663 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
@@ -4611,46 +4668,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4611 goto out; 4668 goto out;
4612 } 4669 }
4613 4670
4614 flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT; 4671 ret = ext4_alloc_file_blocks(file, lblk, max_blocks, flags, mode);
4615 if (mode & FALLOC_FL_KEEP_SIZE) 4672 if (ret)
4616 flags |= EXT4_GET_BLOCKS_KEEP_SIZE; 4673 goto out;
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
4625retry:
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 }
4654 4674
4655 handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); 4675 handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
4656 if (IS_ERR(handle)) 4676 if (IS_ERR(handle))
@@ -4658,14 +4678,14 @@ retry:
4658 4678
4659 tv = inode->i_ctime = ext4_current_time(inode); 4679 tv = inode->i_ctime = ext4_current_time(inode);
4660 4680
4661 if (ret > 0 && new_size) { 4681 if (!ret && new_size) {
4662 if (new_size > i_size_read(inode)) { 4682 if (new_size > i_size_read(inode)) {
4663 i_size_write(inode, new_size); 4683 i_size_write(inode, new_size);
4664 inode->i_mtime = tv; 4684 inode->i_mtime = tv;
4665 } 4685 }
4666 if (new_size > EXT4_I(inode)->i_disksize) 4686 if (new_size > EXT4_I(inode)->i_disksize)
4667 ext4_update_i_disksize(inode, new_size); 4687 ext4_update_i_disksize(inode, new_size);
4668 } else if (ret > 0 && !new_size) { 4688 } else if (!ret && !new_size) {
4669 /* 4689 /*
4670 * Mark that we allocate beyond EOF so the subsequent truncate 4690 * Mark that we allocate beyond EOF so the subsequent truncate
4671 * can proceed even if the new size is the same as i_size. 4691 * can proceed even if the new size is the same as i_size.
@@ -4680,9 +4700,8 @@ retry:
4680 ext4_journal_stop(handle); 4700 ext4_journal_stop(handle);
4681out: 4701out:
4682 mutex_unlock(&inode->i_mutex); 4702 mutex_unlock(&inode->i_mutex);
4683 trace_ext4_fallocate_exit(inode, offset, max_blocks, 4703 trace_ext4_fallocate_exit(inode, offset, max_blocks, ret);
4684 ret > 0 ? ret2 : ret); 4704 return ret;
4685 return ret > 0 ? ret2 : ret;
4686} 4705}
4687 4706
4688/* 4707/*