]> Pileus Git - ~andy/linux/blob - fs/btrfs/tree-defrag.c
Btrfs: Add BH_Defrag to mark buffers that are in need of defragging
[~andy/linux] / fs / btrfs / tree-defrag.c
1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
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.
7  *
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.
12  *
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.
17  */
18
19 #include <linux/sched.h>
20 #include "ctree.h"
21 #include "disk-io.h"
22 #include "print-tree.h"
23 #include "transaction.h"
24
25 static void reada_defrag(struct btrfs_root *root,
26                          struct btrfs_node *node)
27 {
28         int i;
29         u32 nritems;
30         u64 blocknr;
31         int ret;
32
33         nritems = btrfs_header_nritems(&node->header);
34         for (i = 0; i < nritems; i++) {
35                 blocknr = btrfs_node_blockptr(node, i);
36                 ret = readahead_tree_block(root, blocknr);
37                 if (ret)
38                         break;
39         }
40 }
41
42 static int defrag_walk_down(struct btrfs_trans_handle *trans,
43                             struct btrfs_root *root,
44                             struct btrfs_path *path, int *level,
45                             int cache_only, u64 *last_ret)
46 {
47         struct buffer_head *next;
48         struct buffer_head *cur;
49         u64 blocknr;
50         int ret = 0;
51         int is_extent = 0;
52
53         WARN_ON(*level < 0);
54         WARN_ON(*level >= BTRFS_MAX_LEVEL);
55
56         if (root->fs_info->extent_root == root)
57                 is_extent = 1;
58
59         while(*level > 0) {
60                 WARN_ON(*level < 0);
61                 WARN_ON(*level >= BTRFS_MAX_LEVEL);
62                 cur = path->nodes[*level];
63
64                 if (!cache_only && *level > 1 && path->slots[*level] == 0)
65                         reada_defrag(root, btrfs_buffer_node(cur));
66
67                 if (btrfs_header_level(btrfs_buffer_header(cur)) != *level)
68                         WARN_ON(1);
69
70                 if (path->slots[*level] >=
71                     btrfs_header_nritems(btrfs_buffer_header(cur)))
72                         break;
73
74                 if (*level == 1) {
75                         ret = btrfs_realloc_node(trans, root,
76                                                  path->nodes[*level],
77                                                  cache_only, last_ret);
78                         if (is_extent)
79                                 btrfs_extent_post_op(trans, root);
80
81                         break;
82                 }
83                 blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur),
84                                               path->slots[*level]);
85
86                 if (cache_only) {
87                         next = btrfs_find_tree_block(root, blocknr);
88                         if (!next || !buffer_uptodate(next) ||
89                            buffer_locked(next) || !buffer_defrag(next)) {
90                                 brelse(next);
91                                 path->slots[*level]++;
92                                 continue;
93                         }
94                 } else {
95                         next = read_tree_block(root, blocknr);
96                 }
97                 ret = btrfs_cow_block(trans, root, next, path->nodes[*level],
98                                       path->slots[*level], &next);
99                 BUG_ON(ret);
100                 ret = btrfs_realloc_node(trans, root, next, cache_only,
101                                          last_ret);
102                 BUG_ON(ret);
103
104                 if (is_extent)
105                         btrfs_extent_post_op(trans, root);
106
107                 WARN_ON(*level <= 0);
108                 if (path->nodes[*level-1])
109                         btrfs_block_release(root, path->nodes[*level-1]);
110                 path->nodes[*level-1] = next;
111                 *level = btrfs_header_level(btrfs_buffer_header(next));
112                 path->slots[*level] = 0;
113         }
114         WARN_ON(*level < 0);
115         WARN_ON(*level >= BTRFS_MAX_LEVEL);
116         btrfs_block_release(root, path->nodes[*level]);
117         path->nodes[*level] = NULL;
118         *level += 1;
119         WARN_ON(ret);
120         return 0;
121 }
122
123 static int defrag_walk_up(struct btrfs_trans_handle *trans,
124                           struct btrfs_root *root,
125                           struct btrfs_path *path, int *level,
126                           int cache_only)
127 {
128         int i;
129         int slot;
130         struct btrfs_node *node;
131
132         for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
133                 slot = path->slots[i];
134                 if (slot < btrfs_header_nritems(
135                     btrfs_buffer_header(path->nodes[i])) - 1) {
136                         path->slots[i]++;
137                         *level = i;
138                         node = btrfs_buffer_node(path->nodes[i]);
139                         WARN_ON(i == 0);
140                         btrfs_disk_key_to_cpu(&root->defrag_progress,
141                                               &node->ptrs[path->slots[i]].key);
142                         root->defrag_level = i;
143                         return 0;
144                 } else {
145                         clear_buffer_defrag(path->nodes[*level]);
146                         btrfs_block_release(root, path->nodes[*level]);
147                         path->nodes[*level] = NULL;
148                         *level = i + 1;
149                 }
150         }
151         return 1;
152 }
153
154 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
155                         struct btrfs_root *root, int cache_only)
156 {
157         struct btrfs_path *path = NULL;
158         struct buffer_head *tmp;
159         int ret = 0;
160         int wret;
161         int level;
162         int orig_level;
163         int i;
164         int is_extent = 0;
165         u64 last_ret = 0;
166
167         if (root->fs_info->extent_root == root)
168                 is_extent = 1;
169
170         if (root->ref_cows == 0 && !is_extent)
171                 goto out;
172         path = btrfs_alloc_path();
173         if (!path)
174                 return -ENOMEM;
175
176         level = btrfs_header_level(btrfs_buffer_header(root->node));
177         orig_level = level;
178         if (level == 0) {
179                 goto out;
180         }
181         if (root->defrag_progress.objectid == 0) {
182                 get_bh(root->node);
183                 ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp);
184                 BUG_ON(ret);
185                 ret = btrfs_realloc_node(trans, root, root->node, cache_only,
186                                          &last_ret);
187                 BUG_ON(ret);
188                 path->nodes[level] = root->node;
189                 path->slots[level] = 0;
190                 if (is_extent)
191                         btrfs_extent_post_op(trans, root);
192         } else {
193                 level = root->defrag_level;
194                 path->lowest_level = level;
195                 wret = btrfs_search_slot(trans, root, &root->defrag_progress,
196                                          path, 0, 1);
197
198                 if (is_extent)
199                         btrfs_extent_post_op(trans, root);
200                 if (wret < 0) {
201                         ret = wret;
202                         goto out;
203                 }
204                 while(level > 0 && !path->nodes[level])
205                         level--;
206                 if (!path->nodes[level]) {
207                         ret = 0;
208                         goto out;
209                 }
210         }
211
212         while(1) {
213                 wret = defrag_walk_down(trans, root, path, &level, cache_only,
214                                         &last_ret);
215                 if (wret > 0)
216                         break;
217                 if (wret < 0)
218                         ret = wret;
219
220                 wret = defrag_walk_up(trans, root, path, &level, cache_only);
221                 if (wret > 0)
222                         break;
223                 if (wret < 0)
224                         ret = wret;
225                 ret = -EAGAIN;
226                 break;
227         }
228         for (i = 0; i <= orig_level; i++) {
229                 if (path->nodes[i]) {
230                         btrfs_block_release(root, path->nodes[i]);
231                         path->nodes[i] = 0;
232                 }
233         }
234 out:
235         if (path)
236                 btrfs_free_path(path);
237         if (ret != -EAGAIN) {
238                 memset(&root->defrag_progress, 0,
239                        sizeof(root->defrag_progress));
240         }
241         return ret;
242 }