2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include <linux/sched.h>
22 #include "print-tree.h"
23 #include "transaction.h"
25 static void reada_defrag(struct btrfs_root
*root
,
26 struct extent_buffer
*node
)
34 blocksize
= btrfs_level_size(root
, btrfs_header_level(node
) - 1);
35 nritems
= btrfs_header_nritems(node
);
36 for (i
= 0; i
< nritems
; i
++) {
37 bytenr
= btrfs_node_blockptr(node
, i
);
38 ret
= readahead_tree_block(root
, bytenr
, blocksize
);
44 static int defrag_walk_down(struct btrfs_trans_handle
*trans
,
45 struct btrfs_root
*root
,
46 struct btrfs_path
*path
, int *level
,
47 int cache_only
, u64
*last_ret
)
49 struct extent_buffer
*next
;
50 struct extent_buffer
*cur
;
56 WARN_ON(*level
>= BTRFS_MAX_LEVEL
);
58 if (root
->fs_info
->extent_root
== root
)
63 WARN_ON(*level
>= BTRFS_MAX_LEVEL
);
64 cur
= path
->nodes
[*level
];
66 if (!cache_only
&& *level
> 1 && path
->slots
[*level
] == 0)
67 reada_defrag(root
, cur
);
69 if (btrfs_header_level(cur
) != *level
)
72 if (path
->slots
[*level
] >=
73 btrfs_header_nritems(cur
))
77 ret
= btrfs_realloc_node(trans
, root
,
79 cache_only
, last_ret
);
81 btrfs_extent_post_op(trans
, root
);
85 bytenr
= btrfs_node_blockptr(cur
, path
->slots
[*level
]);
88 next
= btrfs_find_tree_block(root
, bytenr
,
89 btrfs_level_size(root
, *level
- 1));
90 /* FIXME, test for defrag */
91 if (!next
|| !btrfs_buffer_uptodate(next
)) {
92 free_extent_buffer(next
);
93 path
->slots
[*level
]++;
97 next
= read_tree_block(root
, bytenr
,
98 btrfs_level_size(root
, *level
- 1));
100 ret
= btrfs_cow_block(trans
, root
, next
, path
->nodes
[*level
],
101 path
->slots
[*level
], &next
);
103 ret
= btrfs_realloc_node(trans
, root
, next
, cache_only
,
108 btrfs_extent_post_op(trans
, root
);
110 WARN_ON(*level
<= 0);
111 if (path
->nodes
[*level
-1])
112 free_extent_buffer(path
->nodes
[*level
-1]);
113 path
->nodes
[*level
-1] = next
;
114 *level
= btrfs_header_level(next
);
115 path
->slots
[*level
] = 0;
118 WARN_ON(*level
>= BTRFS_MAX_LEVEL
);
120 clear_buffer_defrag(path
->nodes
[*level
]);
121 clear_buffer_defrag_done(path
->nodes
[*level
]);
123 free_extent_buffer(path
->nodes
[*level
]);
124 path
->nodes
[*level
] = NULL
;
130 static int defrag_walk_up(struct btrfs_trans_handle
*trans
,
131 struct btrfs_root
*root
,
132 struct btrfs_path
*path
, int *level
,
137 struct extent_buffer
*node
;
139 for(i
= *level
; i
< BTRFS_MAX_LEVEL
- 1 && path
->nodes
[i
]; i
++) {
140 slot
= path
->slots
[i
];
141 if (slot
< btrfs_header_nritems(path
->nodes
[i
]) - 1) {
144 node
= path
->nodes
[i
];
146 btrfs_node_key_to_cpu(node
, &root
->defrag_progress
,
148 root
->defrag_level
= i
;
152 clear_buffer_defrag(path->nodes[*level]);
153 clear_buffer_defrag_done(path->nodes[*level]);
155 free_extent_buffer(path
->nodes
[*level
]);
156 path
->nodes
[*level
] = NULL
;
163 int btrfs_defrag_leaves(struct btrfs_trans_handle
*trans
,
164 struct btrfs_root
*root
, int cache_only
)
166 struct btrfs_path
*path
= NULL
;
167 struct extent_buffer
*tmp
;
176 if (root
->fs_info
->extent_root
== root
)
179 if (root
->ref_cows
== 0 && !is_extent
)
182 path
= btrfs_alloc_path();
186 level
= btrfs_header_level(root
->node
);
191 if (root
->defrag_progress
.objectid
== 0) {
192 extent_buffer_get(root
->node
);
193 ret
= btrfs_cow_block(trans
, root
, root
->node
, NULL
, 0, &tmp
);
195 ret
= btrfs_realloc_node(trans
, root
, root
->node
, cache_only
,
198 path
->nodes
[level
] = root
->node
;
199 path
->slots
[level
] = 0;
201 btrfs_extent_post_op(trans
, root
);
203 level
= root
->defrag_level
;
204 path
->lowest_level
= level
;
205 wret
= btrfs_search_slot(trans
, root
, &root
->defrag_progress
,
209 btrfs_extent_post_op(trans
, root
);
216 while(level
> 0 && !path
->nodes
[level
])
219 if (!path
->nodes
[level
]) {
226 wret
= defrag_walk_down(trans
, root
, path
, &level
, cache_only
,
233 wret
= defrag_walk_up(trans
, root
, path
, &level
, cache_only
);
241 for (i
= 0; i
<= orig_level
; i
++) {
242 if (path
->nodes
[i
]) {
243 free_extent_buffer(path
->nodes
[i
]);
249 btrfs_free_path(path
);
250 if (ret
!= -EAGAIN
) {
251 memset(&root
->defrag_progress
, 0,
252 sizeof(root
->defrag_progress
));
This page took 0.056998 seconds and 5 git commands to generate.