diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index c7e47e77723f..ee1ae00d2827 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -99,7 +99,6 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
99 | if (ret) | 99 | if (ret) |
100 | return ret; | 100 | return ret; |
101 | } else { | 101 | } else { |
102 | WARN_ON(!root->ref_cows); | ||
103 | clean_tree_block(trans, root, buf); | 102 | clean_tree_block(trans, root, buf); |
104 | } | 103 | } |
105 | 104 | ||
@@ -162,13 +161,14 @@ static int close_blocks(u64 blocknr, u64 other) | |||
162 | 161 | ||
163 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 162 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
164 | struct btrfs_root *root, struct buffer_head *parent, | 163 | struct btrfs_root *root, struct buffer_head *parent, |
165 | int cache_only) | 164 | int cache_only, u64 *last_ret) |
166 | { | 165 | { |
167 | struct btrfs_node *parent_node; | 166 | struct btrfs_node *parent_node; |
168 | struct buffer_head *cur_bh; | 167 | struct buffer_head *cur_bh; |
169 | struct buffer_head *tmp_bh; | 168 | struct buffer_head *tmp_bh; |
170 | u64 blocknr; | 169 | u64 blocknr; |
171 | u64 search_start = 0; | 170 | u64 search_start = *last_ret; |
171 | u64 last_block = 0; | ||
172 | u64 other; | 172 | u64 other; |
173 | u32 parent_nritems; | 173 | u32 parent_nritems; |
174 | int start_slot; | 174 | int start_slot; |
@@ -198,6 +198,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
198 | for (i = start_slot; i < end_slot; i++) { | 198 | for (i = start_slot; i < end_slot; i++) { |
199 | int close = 1; | 199 | int close = 1; |
200 | blocknr = btrfs_node_blockptr(parent_node, i); | 200 | blocknr = btrfs_node_blockptr(parent_node, i); |
201 | if (last_block == 0) | ||
202 | last_block = blocknr; | ||
201 | if (i > 0) { | 203 | if (i > 0) { |
202 | other = btrfs_node_blockptr(parent_node, i - 1); | 204 | other = btrfs_node_blockptr(parent_node, i - 1); |
203 | close = close_blocks(blocknr, other); | 205 | close = close_blocks(blocknr, other); |
@@ -206,8 +208,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
206 | other = btrfs_node_blockptr(parent_node, i + 1); | 208 | other = btrfs_node_blockptr(parent_node, i + 1); |
207 | close = close_blocks(blocknr, other); | 209 | close = close_blocks(blocknr, other); |
208 | } | 210 | } |
209 | if (close) | 211 | if (close) { |
212 | last_block = blocknr; | ||
210 | continue; | 213 | continue; |
214 | } | ||
211 | 215 | ||
212 | cur_bh = btrfs_find_tree_block(root, blocknr); | 216 | cur_bh = btrfs_find_tree_block(root, blocknr); |
213 | if (!cur_bh || !buffer_uptodate(cur_bh) || | 217 | if (!cur_bh || !buffer_uptodate(cur_bh) || |
@@ -219,9 +223,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
219 | brelse(cur_bh); | 223 | brelse(cur_bh); |
220 | cur_bh = read_tree_block(root, blocknr); | 224 | cur_bh = read_tree_block(root, blocknr); |
221 | } | 225 | } |
222 | if (search_start == 0) { | 226 | if (search_start == 0) |
223 | search_start = bh_blocknr(cur_bh) & ~((u64)65535); | 227 | search_start = last_block & ~((u64)65535); |
224 | } | 228 | |
225 | err = __btrfs_cow_block(trans, root, cur_bh, parent, i, | 229 | err = __btrfs_cow_block(trans, root, cur_bh, parent, i, |
226 | &tmp_bh, search_start, | 230 | &tmp_bh, search_start, |
227 | min(8, end_slot - i)); | 231 | min(8, end_slot - i)); |