diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-11-06 10:26:24 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 081e95736d9118a96e9f6dcc5cec02dc75c9e1cb (patch) | |
tree | 41c1b692a0ba44223cadae5d78bc3446f963dca1 | |
parent | c549228ff63498025bf0b065c5a5909a06f21647 (diff) |
Btrfs: Make defrag check nodes against the progress key to prevent repeating work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.c | 56 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 3 |
2 files changed, 34 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index eef9c92f86d5..ea9b46699349 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -161,6 +161,31 @@ static int close_blocks(u64 blocknr, u64 other, u32 blocksize) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | /* | ||
165 | * compare two keys in a memcmp fashion | ||
166 | */ | ||
167 | static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | ||
168 | { | ||
169 | struct btrfs_key k1; | ||
170 | |||
171 | btrfs_disk_key_to_cpu(&k1, disk); | ||
172 | |||
173 | if (k1.objectid > k2->objectid) | ||
174 | return 1; | ||
175 | if (k1.objectid < k2->objectid) | ||
176 | return -1; | ||
177 | if (k1.type > k2->type) | ||
178 | return 1; | ||
179 | if (k1.type < k2->type) | ||
180 | return -1; | ||
181 | if (k1.offset > k2->offset) | ||
182 | return 1; | ||
183 | if (k1.offset < k2->offset) | ||
184 | return -1; | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | |||
164 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 189 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
165 | struct btrfs_root *root, struct extent_buffer *parent, | 190 | struct btrfs_root *root, struct extent_buffer *parent, |
166 | int start_slot, int cache_only, u64 *last_ret, | 191 | int start_slot, int cache_only, u64 *last_ret, |
@@ -179,6 +204,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
179 | int parent_level; | 204 | int parent_level; |
180 | int uptodate; | 205 | int uptodate; |
181 | u32 blocksize; | 206 | u32 blocksize; |
207 | int progress_passed = 0; | ||
208 | struct btrfs_disk_key disk_key; | ||
182 | 209 | ||
183 | parent_level = btrfs_header_level(parent); | 210 | parent_level = btrfs_header_level(parent); |
184 | if (cache_only && parent_level != 1) | 211 | if (cache_only && parent_level != 1) |
@@ -213,6 +240,11 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
213 | &parent->map_start, &parent->map_len, | 240 | &parent->map_start, &parent->map_len, |
214 | KM_USER1); | 241 | KM_USER1); |
215 | } | 242 | } |
243 | btrfs_node_key(parent, &disk_key, i); | ||
244 | if (!progress_passed && comp_keys(&disk_key, progress) < 0) | ||
245 | continue; | ||
246 | |||
247 | progress_passed = 1; | ||
216 | blocknr = btrfs_node_blockptr(parent, i); | 248 | blocknr = btrfs_node_blockptr(parent, i); |
217 | if (last_block == 0) | 249 | if (last_block == 0) |
218 | last_block = blocknr; | 250 | last_block = blocknr; |
@@ -292,30 +324,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root, | |||
292 | return btrfs_item_offset_nr(leaf, nr - 1); | 324 | return btrfs_item_offset_nr(leaf, nr - 1); |
293 | } | 325 | } |
294 | 326 | ||
295 | /* | ||
296 | * compare two keys in a memcmp fashion | ||
297 | */ | ||
298 | static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | ||
299 | { | ||
300 | struct btrfs_key k1; | ||
301 | |||
302 | btrfs_disk_key_to_cpu(&k1, disk); | ||
303 | |||
304 | if (k1.objectid > k2->objectid) | ||
305 | return 1; | ||
306 | if (k1.objectid < k2->objectid) | ||
307 | return -1; | ||
308 | if (k1.type > k2->type) | ||
309 | return 1; | ||
310 | if (k1.type < k2->type) | ||
311 | return -1; | ||
312 | if (k1.offset > k2->offset) | ||
313 | return 1; | ||
314 | if (k1.offset < k2->offset) | ||
315 | return -1; | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int check_node(struct btrfs_root *root, struct btrfs_path *path, | 327 | static int check_node(struct btrfs_root *root, struct btrfs_path *path, |
320 | int level) | 328 | int level) |
321 | { | 329 | { |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 65ef12351566..6ef1ba5f9c2f 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -227,7 +227,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
227 | break; | 227 | break; |
228 | if (wret < 0) | 228 | if (wret < 0) |
229 | ret = wret; | 229 | ret = wret; |
230 | ret = -EAGAIN; | 230 | else |
231 | ret = -EAGAIN; | ||
231 | break; | 232 | break; |
232 | } | 233 | } |
233 | for (i = 0; i <= orig_level; i++) { | 234 | for (i = 0; i <= orig_level; i++) { |