root-tree.c 10.8 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

19
#include "ctree.h"
20
#include "transaction.h"
21 22 23
#include "disk-io.h"
#include "print-tree.h"

C
Chris Mason 已提交
24 25 26 27 28
/*
 * lookup the root with the highest offset for a given objectid.  The key we do
 * find is copied into 'key'.  If we find something return 0, otherwise 1, < 0
 * on error.
 */
29 30 31
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
			struct btrfs_root_item *item, struct btrfs_key *key)
{
32
	struct btrfs_path *path;
33
	struct btrfs_key search_key;
34 35
	struct btrfs_key found_key;
	struct extent_buffer *l;
36 37 38 39
	int ret;
	int slot;

	search_key.objectid = objectid;
40
	search_key.type = BTRFS_ROOT_ITEM_KEY;
41
	search_key.offset = (u64)-1;
42

43
	path = btrfs_alloc_path();
T
Tsutomu Itoh 已提交
44 45
	if (!path)
		return -ENOMEM;
46
	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
47 48
	if (ret < 0)
		goto out;
49

50
	BUG_ON(ret == 0);
51 52 53 54
	if (path->slots[0] == 0) {
		ret = 1;
		goto out;
	}
55
	l = path->nodes[0];
56
	slot = path->slots[0] - 1;
57
	btrfs_item_key_to_cpu(l, &found_key, slot);
58 59
	if (found_key.objectid != objectid ||
	    found_key.type != BTRFS_ROOT_ITEM_KEY) {
60 61 62
		ret = 1;
		goto out;
	}
63 64 65 66 67
	if (item)
		read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot),
				   sizeof(*item));
	if (key)
		memcpy(key, &found_key, sizeof(found_key));
68 69
	ret = 0;
out:
70
	btrfs_free_path(path);
71 72 73
	return ret;
}

74 75
void btrfs_set_root_node(struct btrfs_root_item *item,
			 struct extent_buffer *node)
76 77 78 79 80 81
{
	btrfs_set_root_bytenr(item, node->start);
	btrfs_set_root_level(item, btrfs_header_level(node));
	btrfs_set_root_generation(item, btrfs_header_generation(node));
}

C
Chris Mason 已提交
82 83 84
/*
 * copy the data in 'item' into the btree
 */
85 86 87
int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *key, struct btrfs_root_item
		      *item)
88
{
89
	struct btrfs_path *path;
90
	struct extent_buffer *l;
91 92
	int ret;
	int slot;
93
	unsigned long ptr;
94

95
	path = btrfs_alloc_path();
96 97 98
	if (!path)
		return -ENOMEM;

99
	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
100 101
	if (ret < 0) {
		btrfs_abort_transaction(trans, root, ret);
102
		goto out;
103
	}
C
Chris Mason 已提交
104 105 106

	if (ret != 0) {
		btrfs_print_leaf(root, path->nodes[0]);
C
Chris Mason 已提交
107 108 109
		printk(KERN_CRIT "unable to update root key %llu %u %llu\n",
		       (unsigned long long)key->objectid, key->type,
		       (unsigned long long)key->offset);
C
Chris Mason 已提交
110 111 112
		BUG_ON(1);
	}

113
	l = path->nodes[0];
114
	slot = path->slots[0];
115 116
	ptr = btrfs_item_ptr_offset(l, slot);
	write_extent_buffer(l, item, ptr, sizeof(*item));
117
	btrfs_mark_buffer_dirty(path->nodes[0]);
118
out:
119
	btrfs_free_path(path);
120 121 122
	return ret;
}

J
Jeff Mahoney 已提交
123 124
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		      struct btrfs_key *key, struct btrfs_root_item *item)
125
{
J
Jeff Mahoney 已提交
126
	return btrfs_insert_item(trans, root, key, item, sizeof(*item));
127 128
}

C
Chris Mason 已提交
129 130
/*
 * at mount time we want to find all the old transaction snapshots that were in
C
Chris Mason 已提交
131 132 133
 * the process of being deleted if we crashed.  This is any root item with an
 * offset lower than the latest root.  They need to be queued for deletion to
 * finish what was happening when we crashed.
C
Chris Mason 已提交
134
 */
135
int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
136 137 138 139
{
	struct btrfs_root *dead_root;
	struct btrfs_root_item *ri;
	struct btrfs_key key;
140
	struct btrfs_key found_key;
141 142 143
	struct btrfs_path *path;
	int ret;
	u32 nritems;
144
	struct extent_buffer *leaf;
145 146
	int slot;

147
	key.objectid = objectid;
148 149 150 151 152
	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
	key.offset = 0;
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
153 154

again:
155 156 157
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
		goto err;
C
Chris Mason 已提交
158
	while (1) {
159 160
		leaf = path->nodes[0];
		nritems = btrfs_header_nritems(leaf);
161 162 163 164 165
		slot = path->slots[0];
		if (slot >= nritems) {
			ret = btrfs_next_leaf(root, path);
			if (ret)
				break;
166 167
			leaf = path->nodes[0];
			nritems = btrfs_header_nritems(leaf);
168 169
			slot = path->slots[0];
		}
170
		btrfs_item_key_to_cpu(leaf, &key, slot);
171 172
		if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
			goto next;
173 174 175 176 177 178 179

		if (key.objectid < objectid)
			goto next;

		if (key.objectid > objectid)
			break;

180
		ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
181
		if (btrfs_disk_root_refs(leaf, ri) != 0)
182
			goto next;
183

184 185
		memcpy(&found_key, &key, sizeof(key));
		key.offset++;
186
		btrfs_release_path(path);
187 188 189
		dead_root =
			btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
						    &found_key);
A
Aneesh 已提交
190 191
		if (IS_ERR(dead_root)) {
			ret = PTR_ERR(dead_root);
192 193
			goto err;
		}
194

195
		ret = btrfs_add_dead_root(dead_root);
196 197
		if (ret)
			goto err;
198
		goto again;
199 200 201 202 203 204 205 206 207 208
next:
		slot++;
		path->slots[0]++;
	}
	ret = 0;
err:
	btrfs_free_path(path);
	return ret;
}

209 210 211 212 213
int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
{
	struct extent_buffer *leaf;
	struct btrfs_path *path;
	struct btrfs_key key;
214 215
	struct btrfs_key root_key;
	struct btrfs_root *root;
216 217 218 219 220 221 222 223 224 225 226
	int err = 0;
	int ret;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	key.objectid = BTRFS_ORPHAN_OBJECTID;
	key.type = BTRFS_ORPHAN_ITEM_KEY;
	key.offset = 0;

227 228 229
	root_key.type = BTRFS_ROOT_ITEM_KEY;
	root_key.offset = (u64)-1;

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
	while (1) {
		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
		if (ret < 0) {
			err = ret;
			break;
		}

		leaf = path->nodes[0];
		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
			ret = btrfs_next_leaf(tree_root, path);
			if (ret < 0)
				err = ret;
			if (ret != 0)
				break;
			leaf = path->nodes[0];
		}

		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
248
		btrfs_release_path(path);
249 250 251 252 253

		if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
		    key.type != BTRFS_ORPHAN_ITEM_KEY)
			break;

254 255 256 257 258 259 260 261 262 263
		root_key.objectid = key.offset;
		key.offset++;

		root = btrfs_read_fs_root_no_name(tree_root->fs_info,
						  &root_key);
		if (!IS_ERR(root))
			continue;

		ret = PTR_ERR(root);
		if (ret != -ENOENT) {
264 265 266 267
			err = ret;
			break;
		}

268 269 270 271 272
		ret = btrfs_find_dead_roots(tree_root, root_key.objectid);
		if (ret) {
			err = ret;
			break;
		}
273 274 275 276 277 278
	}

	btrfs_free_path(path);
	return err;
}

C
Chris Mason 已提交
279
/* drop the root item for 'key' from 'root' */
280 281
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_key *key)
282
{
283
	struct btrfs_path *path;
284
	int ret;
C
Chris Mason 已提交
285
	struct btrfs_root_item *ri;
286
	struct extent_buffer *leaf;
287

288
	path = btrfs_alloc_path();
T
Tsutomu Itoh 已提交
289 290
	if (!path)
		return -ENOMEM;
291
	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
292 293
	if (ret < 0)
		goto out;
294

295
	BUG_ON(ret != 0);
296 297
	leaf = path->nodes[0];
	ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
C
Chris Mason 已提交
298

299
	ret = btrfs_del_item(trans, root, path);
300
out:
301
	btrfs_free_path(path);
302 303
	return ret;
}
304 305 306

int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
		       struct btrfs_root *tree_root,
307 308 309
		       u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
		       const char *name, int name_len)

310
{
311 312 313
	struct btrfs_path *path;
	struct btrfs_root_ref *ref;
	struct extent_buffer *leaf;
314
	struct btrfs_key key;
315 316
	unsigned long ptr;
	int err = 0;
317 318 319
	int ret;

	path = btrfs_alloc_path();
320 321
	if (!path)
		return -ENOMEM;
322 323

	key.objectid = root_id;
324
	key.type = BTRFS_ROOT_BACKREF_KEY;
325
	key.offset = ref_id;
326
again:
327
	ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
328 329 330 331 332 333 334 335 336 337 338 339 340
	BUG_ON(ret < 0);
	if (ret == 0) {
		leaf = path->nodes[0];
		ref = btrfs_item_ptr(leaf, path->slots[0],
				     struct btrfs_root_ref);

		WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
		WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
		ptr = (unsigned long)(ref + 1);
		WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
		*sequence = btrfs_root_ref_sequence(leaf, ref);

		ret = btrfs_del_item(trans, tree_root, path);
341 342 343 344
		if (ret) {
			err = ret;
			goto out;
		}
345 346 347 348
	} else
		err = -ENOENT;

	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
349
		btrfs_release_path(path);
350 351 352 353 354
		key.objectid = ref_id;
		key.type = BTRFS_ROOT_REF_KEY;
		key.offset = root_id;
		goto again;
	}
355

356
out:
357
	btrfs_free_path(path);
358
	return err;
359 360
}

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
int btrfs_find_root_ref(struct btrfs_root *tree_root,
		   struct btrfs_path *path,
		   u64 root_id, u64 ref_id)
{
	struct btrfs_key key;
	int ret;

	key.objectid = root_id;
	key.type = BTRFS_ROOT_REF_KEY;
	key.offset = ref_id;

	ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
	return ret;
}

376 377 378 379 380 381 382 383 384 385 386 387
/*
 * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
 * or BTRFS_ROOT_BACKREF_KEY.
 *
 * The dirid, sequence, name and name_len refer to the directory entry
 * that is referencing the root.
 *
 * For a forward ref, the root_id is the id of the tree referencing
 * the root and ref_id is the id of the subvol  or snapshot.
 *
 * For a back ref the root_id is the id of the subvol or snapshot and
 * ref_id is the id of the tree referencing it.
388 389
 *
 * Will return 0, -ENOMEM, or anything from the CoW path
390 391 392
 */
int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
		       struct btrfs_root *tree_root,
393
		       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
394 395 396 397 398 399 400 401 402 403
		       const char *name, int name_len)
{
	struct btrfs_key key;
	int ret;
	struct btrfs_path *path;
	struct btrfs_root_ref *ref;
	struct extent_buffer *leaf;
	unsigned long ptr;

	path = btrfs_alloc_path();
404 405
	if (!path)
		return -ENOMEM;
406 407

	key.objectid = root_id;
408
	key.type = BTRFS_ROOT_BACKREF_KEY;
409
	key.offset = ref_id;
410
again:
411 412
	ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
				      sizeof(*ref) + name_len);
413 414 415 416 417
	if (ret) {
		btrfs_abort_transaction(trans, tree_root, ret);
		btrfs_free_path(path);
		return ret;
	}
418 419 420 421 422 423 424 425 426 427

	leaf = path->nodes[0];
	ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
	btrfs_set_root_ref_dirid(leaf, ref, dirid);
	btrfs_set_root_ref_sequence(leaf, ref, sequence);
	btrfs_set_root_ref_name_len(leaf, ref, name_len);
	ptr = (unsigned long)(ref + 1);
	write_extent_buffer(leaf, name, ptr, name_len);
	btrfs_mark_buffer_dirty(leaf);

428
	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
429
		btrfs_release_path(path);
430 431 432 433 434 435
		key.objectid = ref_id;
		key.type = BTRFS_ROOT_REF_KEY;
		key.offset = root_id;
		goto again;
	}

436
	btrfs_free_path(path);
437
	return 0;
438
}
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456

/*
 * Old btrfs forgets to init root_item->flags and root_item->byte_limit
 * for subvolumes. To work around this problem, we steal a bit from
 * root_item->inode_item->flags, and use it to indicate if those fields
 * have been properly initialized.
 */
void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
{
	u64 inode_flags = le64_to_cpu(root_item->inode.flags);

	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
		root_item->inode.flags = cpu_to_le64(inode_flags);
		root_item->flags = 0;
		root_item->byte_limit = 0;
	}
}