root-tree.c 4.5 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 24 25 26
#include "disk-io.h"
#include "print-tree.h"

int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
			struct btrfs_root_item *item, struct btrfs_key *key)
{
27
	struct btrfs_path *path;
28 29 30 31 32 33 34
	struct btrfs_key search_key;
	struct btrfs_leaf *l;
	int ret;
	int slot;

	search_key.objectid = objectid;
	search_key.flags = (u32)-1;
35
	search_key.offset = (u64)-1;
36

37 38 39
	path = btrfs_alloc_path();
	BUG_ON(!path);
	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
40 41 42
	if (ret < 0)
		goto out;
	BUG_ON(ret == 0);
43 44 45
	l = btrfs_buffer_leaf(path->nodes[0]);
	BUG_ON(path->slots[0] == 0);
	slot = path->slots[0] - 1;
46
	if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) {
47 48 49
		ret = 1;
		goto out;
	}
C
Chris Mason 已提交
50
	memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item),
51 52 53 54
		sizeof(*item));
	btrfs_disk_key_to_cpu(key, &l->items[slot].key);
	ret = 0;
out:
55 56
	btrfs_release_path(root, path);
	btrfs_free_path(path);
57 58 59
	return ret;
}

60 61 62
int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *key, struct btrfs_root_item
		      *item)
63
{
64
	struct btrfs_path *path;
65 66 67
	struct btrfs_leaf *l;
	int ret;
	int slot;
C
Chris Mason 已提交
68
	struct btrfs_root_item *update_item;
69

70 71 72
	path = btrfs_alloc_path();
	BUG_ON(!path);
	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
73 74 75
	if (ret < 0)
		goto out;
	BUG_ON(ret != 0);
76 77
	l = btrfs_buffer_leaf(path->nodes[0]);
	slot = path->slots[0];
C
Chris Mason 已提交
78 79
	update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item);
	btrfs_memcpy(root, l, update_item, item, sizeof(*item));
80
	btrfs_mark_buffer_dirty(path->nodes[0]);
81
out:
82 83
	btrfs_release_path(root, path);
	btrfs_free_path(path);
84 85 86
	return ret;
}

87 88 89
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *key, struct btrfs_root_item
		      *item)
90 91
{
	int ret;
92
	ret = btrfs_insert_item(trans, root, key, item, sizeof(*item));
93 94 95
	return ret;
}

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
int btrfs_find_dead_roots(struct btrfs_root *root)
{
	struct btrfs_root *dead_root;
	struct btrfs_item *item;
	struct btrfs_root_item *ri;
	struct btrfs_key key;
	struct btrfs_path *path;
	int ret;
	u32 nritems;
	struct btrfs_leaf *leaf;
	int slot;

	key.objectid = 0;
	key.flags = 0;
	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
	key.offset = 0;
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
		goto err;
	while(1) {
		leaf = btrfs_buffer_leaf(path->nodes[0]);
		nritems = btrfs_header_nritems(&leaf->header);
		slot = path->slots[0];
		if (slot >= nritems) {
			ret = btrfs_next_leaf(root, path);
			if (ret)
				break;
			leaf = btrfs_buffer_leaf(path->nodes[0]);
			nritems = btrfs_header_nritems(&leaf->header);
			slot = path->slots[0];
		}
		item = leaf->items + slot;
		btrfs_disk_key_to_cpu(&key, &item->key);
		if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
			goto next;
		ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
		if (btrfs_root_refs(ri) != 0)
			goto next;
		dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key);
A
Aneesh 已提交
138 139
		if (IS_ERR(dead_root)) {
			ret = PTR_ERR(dead_root);
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
			goto err;
		}
		ret = btrfs_add_dead_root(dead_root,
					  &root->fs_info->dead_roots);
		if (ret)
			goto err;
next:
		slot++;
		path->slots[0]++;
	}
	ret = 0;
err:
	btrfs_free_path(path);
	return ret;
}

156 157
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_key *key)
158
{
159
	struct btrfs_path *path;
160
	int ret;
C
Chris Mason 已提交
161 162
	u32 refs;
	struct btrfs_root_item *ri;
163

164 165 166
	path = btrfs_alloc_path();
	BUG_ON(!path);
	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
167 168 169
	if (ret < 0)
		goto out;
	BUG_ON(ret != 0);
C
Chris Mason 已提交
170 171 172 173
	ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
			    path->slots[0], struct btrfs_root_item);

	refs = btrfs_root_refs(ri);
174 175
	BUG_ON(refs != 0);
	ret = btrfs_del_item(trans, root, path);
176
out:
177 178
	btrfs_release_path(root, path);
	btrfs_free_path(path);
179 180
	return ret;
}