aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2010-05-16 10:49:59 -0400
committerChris Mason <chris.mason@oracle.com>2010-05-25 10:34:53 -0400
commitefa56464562991b8c24f965199888806bd8c4b38 (patch)
treee7c7e69e2931674ddf4f14ac08dfdf43b45de0f4 /fs/btrfs/inode.c
parent4a500fd178c89b96fa166a2d9e7855df33429841 (diff)
Btrfs: Pre-allocate space for data relocation
Pre-allocate space for data relocation. This can detect ENOPSC condition caused by fragmentation of free space. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index bef69bedf3cf..460dd512eebd 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1175,6 +1175,13 @@ out_check:
1175 num_bytes, num_bytes, type); 1175 num_bytes, num_bytes, type);
1176 BUG_ON(ret); 1176 BUG_ON(ret);
1177 1177
1178 if (root->root_key.objectid ==
1179 BTRFS_DATA_RELOC_TREE_OBJECTID) {
1180 ret = btrfs_reloc_clone_csums(inode, cur_offset,
1181 num_bytes);
1182 BUG_ON(ret);
1183 }
1184
1178 extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, 1185 extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
1179 cur_offset, cur_offset + num_bytes - 1, 1186 cur_offset, cur_offset + num_bytes - 1,
1180 locked_page, EXTENT_CLEAR_UNLOCK_PAGE | 1187 locked_page, EXTENT_CLEAR_UNLOCK_PAGE |
@@ -6080,16 +6087,15 @@ out_unlock:
6080 return err; 6087 return err;
6081} 6088}
6082 6089
6083static int prealloc_file_range(struct inode *inode, u64 start, u64 end, 6090int btrfs_prealloc_file_range(struct inode *inode, int mode,
6084 u64 alloc_hint, int mode, loff_t actual_len) 6091 u64 start, u64 num_bytes, u64 min_size,
6092 loff_t actual_len, u64 *alloc_hint)
6085{ 6093{
6086 struct btrfs_trans_handle *trans; 6094 struct btrfs_trans_handle *trans;
6087 struct btrfs_root *root = BTRFS_I(inode)->root; 6095 struct btrfs_root *root = BTRFS_I(inode)->root;
6088 struct btrfs_key ins; 6096 struct btrfs_key ins;
6089 u64 cur_offset = start; 6097 u64 cur_offset = start;
6090 u64 num_bytes = end - start;
6091 int ret = 0; 6098 int ret = 0;
6092 u64 i_size;
6093 6099
6094 while (num_bytes > 0) { 6100 while (num_bytes > 0) {
6095 trans = btrfs_start_transaction(root, 3); 6101 trans = btrfs_start_transaction(root, 3);
@@ -6098,9 +6104,8 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
6098 break; 6104 break;
6099 } 6105 }
6100 6106
6101 ret = btrfs_reserve_extent(trans, root, num_bytes, 6107 ret = btrfs_reserve_extent(trans, root, num_bytes, min_size,
6102 root->sectorsize, 0, alloc_hint, 6108 0, *alloc_hint, (u64)-1, &ins, 1);
6103 (u64)-1, &ins, 1);
6104 if (ret) { 6109 if (ret) {
6105 btrfs_end_transaction(trans, root); 6110 btrfs_end_transaction(trans, root);
6106 break; 6111 break;
@@ -6117,20 +6122,19 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
6117 6122
6118 num_bytes -= ins.offset; 6123 num_bytes -= ins.offset;
6119 cur_offset += ins.offset; 6124 cur_offset += ins.offset;
6120 alloc_hint = ins.objectid + ins.offset; 6125 *alloc_hint = ins.objectid + ins.offset;
6121 6126
6122 inode->i_ctime = CURRENT_TIME; 6127 inode->i_ctime = CURRENT_TIME;
6123 BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC; 6128 BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
6124 if (!(mode & FALLOC_FL_KEEP_SIZE) && 6129 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
6125 (actual_len > inode->i_size) && 6130 (actual_len > inode->i_size) &&
6126 (cur_offset > inode->i_size)) { 6131 (cur_offset > inode->i_size)) {
6127
6128 if (cur_offset > actual_len) 6132 if (cur_offset > actual_len)
6129 i_size = actual_len; 6133 i_size_write(inode, actual_len);
6130 else 6134 else
6131 i_size = cur_offset; 6135 i_size_write(inode, cur_offset);
6132 i_size_write(inode, i_size); 6136 i_size_write(inode, cur_offset);
6133 btrfs_ordered_update_i_size(inode, i_size, NULL); 6137 btrfs_ordered_update_i_size(inode, cur_offset, NULL);
6134 } 6138 }
6135 6139
6136 ret = btrfs_update_inode(trans, root, inode); 6140 ret = btrfs_update_inode(trans, root, inode);
@@ -6216,16 +6220,16 @@ static long btrfs_fallocate(struct inode *inode, int mode,
6216 if (em->block_start == EXTENT_MAP_HOLE || 6220 if (em->block_start == EXTENT_MAP_HOLE ||
6217 (cur_offset >= inode->i_size && 6221 (cur_offset >= inode->i_size &&
6218 !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { 6222 !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
6219 ret = prealloc_file_range(inode, 6223 ret = btrfs_prealloc_file_range(inode, 0, cur_offset,
6220 cur_offset, last_byte, 6224 last_byte - cur_offset,
6221 alloc_hint, mode, offset+len); 6225 1 << inode->i_blkbits,
6226 offset + len,
6227 &alloc_hint);
6222 if (ret < 0) { 6228 if (ret < 0) {
6223 free_extent_map(em); 6229 free_extent_map(em);
6224 break; 6230 break;
6225 } 6231 }
6226 } 6232 }
6227 if (em->block_start <= EXTENT_MAP_LAST_BYTE)
6228 alloc_hint = em->block_start;
6229 free_extent_map(em); 6233 free_extent_map(em);
6230 6234
6231 cur_offset = last_byte; 6235 cur_offset = last_byte;