Branch data Line data Source code
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/uuid.h>
20 : : #include "ctree.h"
21 : : #include "transaction.h"
22 : : #include "disk-io.h"
23 : : #include "print-tree.h"
24 : :
25 : : /*
26 : : * Read a root item from the tree. In case we detect a root item smaller then
27 : : * sizeof(root_item), we know it's an old version of the root structure and
28 : : * initialize all new fields to zero. The same happens if we detect mismatching
29 : : * generation numbers as then we know the root was once mounted with an older
30 : : * kernel that was not aware of the root item structure change.
31 : : */
32 : 0 : static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
33 : : struct btrfs_root_item *item)
34 : : {
35 : : uuid_le uuid;
36 : : int len;
37 : : int need_reset = 0;
38 : :
39 : 0 : len = btrfs_item_size_nr(eb, slot);
40 : 0 : read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
41 : 0 : min_t(int, len, (int)sizeof(*item)));
42 [ # # ]: 0 : if (len < sizeof(*item))
43 : : need_reset = 1;
44 [ # # ][ # # ]: 0 : if (!need_reset && btrfs_root_generation(item)
45 : : != btrfs_root_generation_v2(item)) {
46 [ # # ]: 0 : if (btrfs_root_generation_v2(item) != 0) {
47 : 0 : printk(KERN_WARNING "BTRFS: mismatching "
48 : : "generation and generation_v2 "
49 : : "found in root item. This root "
50 : : "was probably mounted with an "
51 : : "older kernel. Resetting all "
52 : : "new fields.\n");
53 : : }
54 : : need_reset = 1;
55 : : }
56 [ # # ]: 0 : if (need_reset) {
57 : 0 : memset(&item->generation_v2, 0,
58 : : sizeof(*item) - offsetof(struct btrfs_root_item,
59 : : generation_v2));
60 : :
61 : 0 : uuid_le_gen(&uuid);
62 : 0 : memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE);
63 : : }
64 : 0 : }
65 : :
66 : : /*
67 : : * btrfs_find_root - lookup the root by the key.
68 : : * root: the root of the root tree
69 : : * search_key: the key to search
70 : : * path: the path we search
71 : : * root_item: the root item of the tree we look for
72 : : * root_key: the reak key of the tree we look for
73 : : *
74 : : * If ->offset of 'seach_key' is -1ULL, it means we are not sure the offset
75 : : * of the search key, just lookup the root with the highest offset for a
76 : : * given objectid.
77 : : *
78 : : * If we find something return 0, otherwise > 0, < 0 on error.
79 : : */
80 : 0 : int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
81 : : struct btrfs_path *path, struct btrfs_root_item *root_item,
82 : : struct btrfs_key *root_key)
83 : : {
84 : : struct btrfs_key found_key;
85 : : struct extent_buffer *l;
86 : : int ret;
87 : : int slot;
88 : :
89 : 0 : ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
90 [ # # ]: 0 : if (ret < 0)
91 : : return ret;
92 : :
93 [ # # ]: 0 : if (search_key->offset != -1ULL) { /* the search key is exact */
94 [ # # ]: 0 : if (ret > 0)
95 : : goto out;
96 : : } else {
97 [ # # ]: 0 : BUG_ON(ret == 0); /* Logical error */
98 [ # # ]: 0 : if (path->slots[0] == 0)
99 : : goto out;
100 : 0 : path->slots[0]--;
101 : : ret = 0;
102 : : }
103 : :
104 : 0 : l = path->nodes[0];
105 : 0 : slot = path->slots[0];
106 : :
107 : : btrfs_item_key_to_cpu(l, &found_key, slot);
108 [ # # ][ # # ]: 0 : if (found_key.objectid != search_key->objectid ||
109 : : found_key.type != BTRFS_ROOT_ITEM_KEY) {
110 : : ret = 1;
111 : : goto out;
112 : : }
113 : :
114 [ # # ]: 0 : if (root_item)
115 : 0 : btrfs_read_root_item(l, slot, root_item);
116 [ # # ]: 0 : if (root_key)
117 : 0 : memcpy(root_key, &found_key, sizeof(found_key));
118 : : out:
119 : 0 : btrfs_release_path(path);
120 : 0 : return ret;
121 : : }
122 : :
123 : 0 : void btrfs_set_root_node(struct btrfs_root_item *item,
124 : 0 : struct extent_buffer *node)
125 : : {
126 : 0 : btrfs_set_root_bytenr(item, node->start);
127 : : btrfs_set_root_level(item, btrfs_header_level(node));
128 : : btrfs_set_root_generation(item, btrfs_header_generation(node));
129 : 0 : }
130 : :
131 : : /*
132 : : * copy the data in 'item' into the btree
133 : : */
134 : 0 : int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
135 : : *root, struct btrfs_key *key, struct btrfs_root_item
136 : : *item)
137 : : {
138 : : struct btrfs_path *path;
139 : : struct extent_buffer *l;
140 : : int ret;
141 : : int slot;
142 : : unsigned long ptr;
143 : : int old_len;
144 : :
145 : 0 : path = btrfs_alloc_path();
146 [ # # ]: 0 : if (!path)
147 : : return -ENOMEM;
148 : :
149 : 0 : ret = btrfs_search_slot(trans, root, key, path, 0, 1);
150 [ # # ]: 0 : if (ret < 0) {
151 : 0 : btrfs_abort_transaction(trans, root, ret);
152 : 0 : goto out;
153 : : }
154 : :
155 [ # # ]: 0 : if (ret != 0) {
156 : 0 : btrfs_print_leaf(root, path->nodes[0]);
157 : 0 : btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu",
158 : : key->objectid, key->type, key->offset);
159 : 0 : BUG_ON(1);
160 : : }
161 : :
162 : 0 : l = path->nodes[0];
163 : 0 : slot = path->slots[0];
164 : 0 : ptr = btrfs_item_ptr_offset(l, slot);
165 : : old_len = btrfs_item_size_nr(l, slot);
166 : :
167 : : /*
168 : : * If this is the first time we update the root item which originated
169 : : * from an older kernel, we need to enlarge the item size to make room
170 : : * for the added fields.
171 : : */
172 [ # # ]: 0 : if (old_len < sizeof(*item)) {
173 : 0 : btrfs_release_path(path);
174 : 0 : ret = btrfs_search_slot(trans, root, key, path,
175 : : -1, 1);
176 [ # # ]: 0 : if (ret < 0) {
177 : 0 : btrfs_abort_transaction(trans, root, ret);
178 : 0 : goto out;
179 : : }
180 : :
181 : : ret = btrfs_del_item(trans, root, path);
182 [ # # ]: 0 : if (ret < 0) {
183 : 0 : btrfs_abort_transaction(trans, root, ret);
184 : 0 : goto out;
185 : : }
186 : 0 : btrfs_release_path(path);
187 : : ret = btrfs_insert_empty_item(trans, root, path,
188 : : key, sizeof(*item));
189 [ # # ]: 0 : if (ret < 0) {
190 : 0 : btrfs_abort_transaction(trans, root, ret);
191 : 0 : goto out;
192 : : }
193 : 0 : l = path->nodes[0];
194 : 0 : slot = path->slots[0];
195 : 0 : ptr = btrfs_item_ptr_offset(l, slot);
196 : : }
197 : :
198 : : /*
199 : : * Update generation_v2 so at the next mount we know the new root
200 : : * fields are valid.
201 : : */
202 : : btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
203 : :
204 : 0 : write_extent_buffer(l, item, ptr, sizeof(*item));
205 : 0 : btrfs_mark_buffer_dirty(path->nodes[0]);
206 : : out:
207 : 0 : btrfs_free_path(path);
208 : 0 : return ret;
209 : : }
210 : :
211 : 0 : int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
212 : : struct btrfs_key *key, struct btrfs_root_item *item)
213 : : {
214 : : /*
215 : : * Make sure generation v1 and v2 match. See update_root for details.
216 : : */
217 : : btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
218 : 0 : return btrfs_insert_item(trans, root, key, item, sizeof(*item));
219 : : }
220 : :
221 : 0 : int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
222 : : {
223 : 0 : struct extent_buffer *leaf;
224 : : struct btrfs_path *path;
225 : : struct btrfs_key key;
226 : : struct btrfs_key root_key;
227 : : struct btrfs_root *root;
228 : : int err = 0;
229 : : int ret;
230 : : bool can_recover = true;
231 : :
232 : : if (tree_root->fs_info->sb->s_flags & MS_RDONLY)
233 : : can_recover = false;
234 : :
235 : 0 : path = btrfs_alloc_path();
236 [ # # ]: 0 : if (!path)
237 : : return -ENOMEM;
238 : :
239 : 0 : key.objectid = BTRFS_ORPHAN_OBJECTID;
240 : 0 : key.type = BTRFS_ORPHAN_ITEM_KEY;
241 : 0 : key.offset = 0;
242 : :
243 : 0 : root_key.type = BTRFS_ROOT_ITEM_KEY;
244 : 0 : root_key.offset = (u64)-1;
245 : :
246 : : while (1) {
247 : 0 : ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
248 [ # # ]: 0 : if (ret < 0) {
249 : : err = ret;
250 : : break;
251 : : }
252 : :
253 : 0 : leaf = path->nodes[0];
254 [ # # ]: 0 : if (path->slots[0] >= btrfs_header_nritems(leaf)) {
255 : 0 : ret = btrfs_next_leaf(tree_root, path);
256 [ # # ]: 0 : if (ret < 0)
257 : : err = ret;
258 [ # # ]: 0 : if (ret != 0)
259 : : break;
260 : 0 : leaf = path->nodes[0];
261 : : }
262 : :
263 : 0 : btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
264 : 0 : btrfs_release_path(path);
265 : :
266 [ # # ][ # # ]: 0 : if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
267 : 0 : key.type != BTRFS_ORPHAN_ITEM_KEY)
268 : : break;
269 : :
270 : 0 : root_key.objectid = key.offset;
271 : 0 : key.offset++;
272 : :
273 : 0 : root = btrfs_read_fs_root(tree_root, &root_key);
274 : : err = PTR_RET(root);
275 [ # # ]: 0 : if (err && err != -ENOENT) {
276 : : break;
277 [ # # ]: 0 : } else if (err == -ENOENT) {
278 : : struct btrfs_trans_handle *trans;
279 : :
280 : 0 : btrfs_release_path(path);
281 : :
282 : 0 : trans = btrfs_join_transaction(tree_root);
283 [ # # ]: 0 : if (IS_ERR(trans)) {
284 : : err = PTR_ERR(trans);
285 : 0 : btrfs_error(tree_root->fs_info, err,
286 : : "Failed to start trans to delete "
287 : : "orphan item");
288 : 0 : break;
289 : : }
290 : 0 : err = btrfs_del_orphan_item(trans, tree_root,
291 : : root_key.objectid);
292 : 0 : btrfs_end_transaction(trans, tree_root);
293 [ # # ]: 0 : if (err) {
294 : 0 : btrfs_error(tree_root->fs_info, err,
295 : : "Failed to delete root orphan "
296 : : "item");
297 : 0 : break;
298 : : }
299 : 0 : continue;
300 : : }
301 : :
302 : 0 : err = btrfs_init_fs_root(root);
303 [ # # ]: 0 : if (err) {
304 : 0 : btrfs_free_fs_root(root);
305 : 0 : break;
306 : : }
307 : :
308 : 0 : root->orphan_item_inserted = 1;
309 : :
310 : 0 : err = btrfs_insert_fs_root(root->fs_info, root);
311 [ # # ]: 0 : if (err) {
312 [ # # ]: 0 : BUG_ON(err == -EEXIST);
313 : 0 : btrfs_free_fs_root(root);
314 : 0 : break;
315 : : }
316 : :
317 [ # # ]: 0 : if (btrfs_root_refs(&root->root_item) == 0)
318 : 0 : btrfs_add_dead_root(root);
319 : : }
320 : :
321 : 0 : btrfs_free_path(path);
322 : 0 : return err;
323 : : }
324 : :
325 : : /* drop the root item for 'key' from 'root' */
326 : 0 : int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
327 : : struct btrfs_key *key)
328 : : {
329 : : struct btrfs_path *path;
330 : : int ret;
331 : :
332 : 0 : path = btrfs_alloc_path();
333 [ # # ]: 0 : if (!path)
334 : : return -ENOMEM;
335 : 0 : ret = btrfs_search_slot(trans, root, key, path, -1, 1);
336 [ # # ]: 0 : if (ret < 0)
337 : : goto out;
338 : :
339 [ # # ]: 0 : BUG_ON(ret != 0);
340 : :
341 : : ret = btrfs_del_item(trans, root, path);
342 : : out:
343 : 0 : btrfs_free_path(path);
344 : 0 : return ret;
345 : : }
346 : :
347 : 0 : int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
348 : : struct btrfs_root *tree_root,
349 : : u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
350 : : const char *name, int name_len)
351 : :
352 : : {
353 : : struct btrfs_path *path;
354 : : struct btrfs_root_ref *ref;
355 : : struct extent_buffer *leaf;
356 : : struct btrfs_key key;
357 : : unsigned long ptr;
358 : : int err = 0;
359 : : int ret;
360 : :
361 : 0 : path = btrfs_alloc_path();
362 [ # # ]: 0 : if (!path)
363 : : return -ENOMEM;
364 : :
365 : 0 : key.objectid = root_id;
366 : 0 : key.type = BTRFS_ROOT_BACKREF_KEY;
367 : 0 : key.offset = ref_id;
368 : : again:
369 : 0 : ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
370 [ # # ]: 0 : BUG_ON(ret < 0);
371 [ # # ]: 0 : if (ret == 0) {
372 : 0 : leaf = path->nodes[0];
373 : 0 : ref = btrfs_item_ptr(leaf, path->slots[0],
374 : : struct btrfs_root_ref);
375 : :
376 [ # # ]: 0 : WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
377 [ # # ]: 0 : WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
378 : 0 : ptr = (unsigned long)(ref + 1);
379 [ # # ]: 0 : WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
380 : 0 : *sequence = btrfs_root_ref_sequence(leaf, ref);
381 : :
382 : : ret = btrfs_del_item(trans, tree_root, path);
383 [ # # ]: 0 : if (ret) {
384 : : err = ret;
385 : : goto out;
386 : : }
387 : : } else
388 : : err = -ENOENT;
389 : :
390 [ # # ]: 0 : if (key.type == BTRFS_ROOT_BACKREF_KEY) {
391 : 0 : btrfs_release_path(path);
392 : 0 : key.objectid = ref_id;
393 : 0 : key.type = BTRFS_ROOT_REF_KEY;
394 : 0 : key.offset = root_id;
395 : 0 : goto again;
396 : : }
397 : :
398 : : out:
399 : 0 : btrfs_free_path(path);
400 : 0 : return err;
401 : : }
402 : :
403 : : /*
404 : : * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY
405 : : * or BTRFS_ROOT_BACKREF_KEY.
406 : : *
407 : : * The dirid, sequence, name and name_len refer to the directory entry
408 : : * that is referencing the root.
409 : : *
410 : : * For a forward ref, the root_id is the id of the tree referencing
411 : : * the root and ref_id is the id of the subvol or snapshot.
412 : : *
413 : : * For a back ref the root_id is the id of the subvol or snapshot and
414 : : * ref_id is the id of the tree referencing it.
415 : : *
416 : : * Will return 0, -ENOMEM, or anything from the CoW path
417 : : */
418 : 0 : int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
419 : : struct btrfs_root *tree_root,
420 : : u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
421 : : const char *name, int name_len)
422 : : {
423 : : struct btrfs_key key;
424 : : int ret;
425 : : struct btrfs_path *path;
426 : : struct btrfs_root_ref *ref;
427 : : struct extent_buffer *leaf;
428 : : unsigned long ptr;
429 : :
430 : 0 : path = btrfs_alloc_path();
431 [ # # ]: 0 : if (!path)
432 : : return -ENOMEM;
433 : :
434 : 0 : key.objectid = root_id;
435 : 0 : key.type = BTRFS_ROOT_BACKREF_KEY;
436 : 0 : key.offset = ref_id;
437 : : again:
438 : 0 : ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
439 : : sizeof(*ref) + name_len);
440 [ # # ]: 0 : if (ret) {
441 : 0 : btrfs_abort_transaction(trans, tree_root, ret);
442 : 0 : btrfs_free_path(path);
443 : 0 : return ret;
444 : : }
445 : :
446 : 0 : leaf = path->nodes[0];
447 : 0 : ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
448 : : btrfs_set_root_ref_dirid(leaf, ref, dirid);
449 : : btrfs_set_root_ref_sequence(leaf, ref, sequence);
450 : 0 : btrfs_set_root_ref_name_len(leaf, ref, name_len);
451 : 0 : ptr = (unsigned long)(ref + 1);
452 : 0 : write_extent_buffer(leaf, name, ptr, name_len);
453 : 0 : btrfs_mark_buffer_dirty(leaf);
454 : :
455 [ # # ]: 0 : if (key.type == BTRFS_ROOT_BACKREF_KEY) {
456 : 0 : btrfs_release_path(path);
457 : 0 : key.objectid = ref_id;
458 : 0 : key.type = BTRFS_ROOT_REF_KEY;
459 : 0 : key.offset = root_id;
460 : 0 : goto again;
461 : : }
462 : :
463 : 0 : btrfs_free_path(path);
464 : 0 : return 0;
465 : : }
466 : :
467 : : /*
468 : : * Old btrfs forgets to init root_item->flags and root_item->byte_limit
469 : : * for subvolumes. To work around this problem, we steal a bit from
470 : : * root_item->inode_item->flags, and use it to indicate if those fields
471 : : * have been properly initialized.
472 : : */
473 : 0 : void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
474 : : {
475 : : u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode);
476 : :
477 [ # # ]: 0 : if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
478 : 0 : inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
479 : : btrfs_set_stack_inode_flags(&root_item->inode, inode_flags);
480 : : btrfs_set_root_flags(root_item, 0);
481 : : btrfs_set_root_limit(root_item, 0);
482 : : }
483 : 0 : }
484 : :
485 : 0 : void btrfs_update_root_times(struct btrfs_trans_handle *trans,
486 : : struct btrfs_root *root)
487 : : {
488 : : struct btrfs_root_item *item = &root->root_item;
489 : 0 : struct timespec ct = CURRENT_TIME;
490 : :
491 : : spin_lock(&root->root_item_lock);
492 : 0 : btrfs_set_root_ctransid(item, trans->transid);
493 : 0 : btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
494 : 0 : btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);
495 : : spin_unlock(&root->root_item_lock);
496 : 0 : }
|