xref: /linux/fs/btrfs/root-tree.c (revision 0132761017e012ab4dc8584d679503f2ba26ca86)
16cbd5570SChris Mason /*
26cbd5570SChris Mason  * Copyright (C) 2007 Oracle.  All rights reserved.
36cbd5570SChris Mason  *
46cbd5570SChris Mason  * This program is free software; you can redistribute it and/or
56cbd5570SChris Mason  * modify it under the terms of the GNU General Public
66cbd5570SChris Mason  * License v2 as published by the Free Software Foundation.
76cbd5570SChris Mason  *
86cbd5570SChris Mason  * This program is distributed in the hope that it will be useful,
96cbd5570SChris Mason  * but WITHOUT ANY WARRANTY; without even the implied warranty of
106cbd5570SChris Mason  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
116cbd5570SChris Mason  * General Public License for more details.
126cbd5570SChris Mason  *
136cbd5570SChris Mason  * You should have received a copy of the GNU General Public
146cbd5570SChris Mason  * License along with this program; if not, write to the
156cbd5570SChris Mason  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
166cbd5570SChris Mason  * Boston, MA 021110-1307, USA.
176cbd5570SChris Mason  */
186cbd5570SChris Mason 
19886322e8SSachin Kamat #include <linux/err.h>
208ea05e3aSAlexander Block #include <linux/uuid.h>
213768f368SChris Mason #include "ctree.h"
225eda7b5eSChris Mason #include "transaction.h"
233768f368SChris Mason #include "disk-io.h"
243768f368SChris Mason #include "print-tree.h"
253768f368SChris Mason 
26bf4ef679SChris Mason /*
278ea05e3aSAlexander Block  * Read a root item from the tree. In case we detect a root item smaller then
288ea05e3aSAlexander Block  * sizeof(root_item), we know it's an old version of the root structure and
298ea05e3aSAlexander Block  * initialize all new fields to zero. The same happens if we detect mismatching
308ea05e3aSAlexander Block  * generation numbers as then we know the root was once mounted with an older
318ea05e3aSAlexander Block  * kernel that was not aware of the root item structure change.
328ea05e3aSAlexander Block  */
33171170c1SSergei Trofimovich static void btrfs_read_root_item(struct extent_buffer *eb, int slot,
348ea05e3aSAlexander Block 				struct btrfs_root_item *item)
358ea05e3aSAlexander Block {
368ea05e3aSAlexander Block 	uuid_le uuid;
378ea05e3aSAlexander Block 	int len;
388ea05e3aSAlexander Block 	int need_reset = 0;
398ea05e3aSAlexander Block 
408ea05e3aSAlexander Block 	len = btrfs_item_size_nr(eb, slot);
418ea05e3aSAlexander Block 	read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
428ea05e3aSAlexander Block 			min_t(int, len, (int)sizeof(*item)));
438ea05e3aSAlexander Block 	if (len < sizeof(*item))
448ea05e3aSAlexander Block 		need_reset = 1;
458ea05e3aSAlexander Block 	if (!need_reset && btrfs_root_generation(item)
468ea05e3aSAlexander Block 		!= btrfs_root_generation_v2(item)) {
478ea05e3aSAlexander Block 		if (btrfs_root_generation_v2(item) != 0) {
48f14d104dSDavid Sterba 			btrfs_warn(eb->fs_info,
49f14d104dSDavid Sterba 					"mismatching "
508ea05e3aSAlexander Block 					"generation and generation_v2 "
518ea05e3aSAlexander Block 					"found in root item. This root "
528ea05e3aSAlexander Block 					"was probably mounted with an "
538ea05e3aSAlexander Block 					"older kernel. Resetting all "
54f14d104dSDavid Sterba 					"new fields.");
558ea05e3aSAlexander Block 		}
568ea05e3aSAlexander Block 		need_reset = 1;
578ea05e3aSAlexander Block 	}
588ea05e3aSAlexander Block 	if (need_reset) {
598ea05e3aSAlexander Block 		memset(&item->generation_v2, 0,
608ea05e3aSAlexander Block 			sizeof(*item) - offsetof(struct btrfs_root_item,
618ea05e3aSAlexander Block 					generation_v2));
628ea05e3aSAlexander Block 
638ea05e3aSAlexander Block 		uuid_le_gen(&uuid);
648ea05e3aSAlexander Block 		memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE);
658ea05e3aSAlexander Block 	}
668ea05e3aSAlexander Block }
678ea05e3aSAlexander Block 
688ea05e3aSAlexander Block /*
69cb517eabSMiao Xie  * btrfs_find_root - lookup the root by the key.
70cb517eabSMiao Xie  * root: the root of the root tree
71cb517eabSMiao Xie  * search_key: the key to search
72cb517eabSMiao Xie  * path: the path we search
73cb517eabSMiao Xie  * root_item: the root item of the tree we look for
74*01327610SNicholas D Steeves  * root_key: the root key of the tree we look for
75cb517eabSMiao Xie  *
76*01327610SNicholas D Steeves  * If ->offset of 'search_key' is -1ULL, it means we are not sure the offset
77cb517eabSMiao Xie  * of the search key, just lookup the root with the highest offset for a
78cb517eabSMiao Xie  * given objectid.
79cb517eabSMiao Xie  *
80cb517eabSMiao Xie  * If we find something return 0, otherwise > 0, < 0 on error.
81d352ac68SChris Mason  */
82cb517eabSMiao Xie int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key,
83cb517eabSMiao Xie 		    struct btrfs_path *path, struct btrfs_root_item *root_item,
84cb517eabSMiao Xie 		    struct btrfs_key *root_key)
853768f368SChris Mason {
865f39d397SChris Mason 	struct btrfs_key found_key;
875f39d397SChris Mason 	struct extent_buffer *l;
883768f368SChris Mason 	int ret;
893768f368SChris Mason 	int slot;
903768f368SChris Mason 
91cb517eabSMiao Xie 	ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);
923768f368SChris Mason 	if (ret < 0)
93cb517eabSMiao Xie 		return ret;
945f39d397SChris Mason 
95cb517eabSMiao Xie 	if (search_key->offset != -1ULL) {	/* the search key is exact */
96cb517eabSMiao Xie 		if (ret > 0)
973768f368SChris Mason 			goto out;
98cb517eabSMiao Xie 	} else {
99cb517eabSMiao Xie 		BUG_ON(ret == 0);		/* Logical error */
100cb517eabSMiao Xie 		if (path->slots[0] == 0)
101cb517eabSMiao Xie 			goto out;
102cb517eabSMiao Xie 		path->slots[0]--;
103cb517eabSMiao Xie 		ret = 0;
1043768f368SChris Mason 	}
105cb517eabSMiao Xie 
10676dda93cSYan, Zheng 	l = path->nodes[0];
107cb517eabSMiao Xie 	slot = path->slots[0];
108cb517eabSMiao Xie 
10976dda93cSYan, Zheng 	btrfs_item_key_to_cpu(l, &found_key, slot);
110cb517eabSMiao Xie 	if (found_key.objectid != search_key->objectid ||
11176dda93cSYan, Zheng 	    found_key.type != BTRFS_ROOT_ITEM_KEY) {
11276dda93cSYan, Zheng 		ret = 1;
11376dda93cSYan, Zheng 		goto out;
11476dda93cSYan, Zheng 	}
1158ea05e3aSAlexander Block 
116cb517eabSMiao Xie 	if (root_item)
117cb517eabSMiao Xie 		btrfs_read_root_item(l, slot, root_item);
118cb517eabSMiao Xie 	if (root_key)
119cb517eabSMiao Xie 		memcpy(root_key, &found_key, sizeof(found_key));
1203768f368SChris Mason out:
121cb517eabSMiao Xie 	btrfs_release_path(path);
1223768f368SChris Mason 	return ret;
1233768f368SChris Mason }
1243768f368SChris Mason 
125bf5f32ecSMark Fasheh void btrfs_set_root_node(struct btrfs_root_item *item,
1265d4f98a2SYan Zheng 			 struct extent_buffer *node)
1275d4f98a2SYan Zheng {
1285d4f98a2SYan Zheng 	btrfs_set_root_bytenr(item, node->start);
1295d4f98a2SYan Zheng 	btrfs_set_root_level(item, btrfs_header_level(node));
1305d4f98a2SYan Zheng 	btrfs_set_root_generation(item, btrfs_header_generation(node));
1315d4f98a2SYan Zheng }
1325d4f98a2SYan Zheng 
133d352ac68SChris Mason /*
134d352ac68SChris Mason  * copy the data in 'item' into the btree
135d352ac68SChris Mason  */
136e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
137e089f05cSChris Mason 		      *root, struct btrfs_key *key, struct btrfs_root_item
138e089f05cSChris Mason 		      *item)
1393768f368SChris Mason {
1405caf2a00SChris Mason 	struct btrfs_path *path;
1415f39d397SChris Mason 	struct extent_buffer *l;
1423768f368SChris Mason 	int ret;
1433768f368SChris Mason 	int slot;
1445f39d397SChris Mason 	unsigned long ptr;
1450412e58cSAlexandru Moise 	u32 old_len;
1463768f368SChris Mason 
1475caf2a00SChris Mason 	path = btrfs_alloc_path();
148b45a9d8bSJeff Mahoney 	if (!path)
149b45a9d8bSJeff Mahoney 		return -ENOMEM;
150b45a9d8bSJeff Mahoney 
1515caf2a00SChris Mason 	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
152005d6427SDavid Sterba 	if (ret < 0) {
153005d6427SDavid Sterba 		btrfs_abort_transaction(trans, root, ret);
154005d6427SDavid Sterba 		goto out;
155005d6427SDavid Sterba 	}
156d6667462SChris Mason 
157d6667462SChris Mason 	if (ret != 0) {
158d6667462SChris Mason 		btrfs_print_leaf(root, path->nodes[0]);
159efe120a0SFrank Holton 		btrfs_crit(root->fs_info, "unable to update root key %llu %u %llu",
160c1c9ff7cSGeert Uytterhoeven 		       key->objectid, key->type, key->offset);
161d6667462SChris Mason 		BUG_ON(1);
162d6667462SChris Mason 	}
163d6667462SChris Mason 
1645f39d397SChris Mason 	l = path->nodes[0];
1655caf2a00SChris Mason 	slot = path->slots[0];
1665f39d397SChris Mason 	ptr = btrfs_item_ptr_offset(l, slot);
1678ea05e3aSAlexander Block 	old_len = btrfs_item_size_nr(l, slot);
1688ea05e3aSAlexander Block 
1698ea05e3aSAlexander Block 	/*
1708ea05e3aSAlexander Block 	 * If this is the first time we update the root item which originated
1718ea05e3aSAlexander Block 	 * from an older kernel, we need to enlarge the item size to make room
1728ea05e3aSAlexander Block 	 * for the added fields.
1738ea05e3aSAlexander Block 	 */
1748ea05e3aSAlexander Block 	if (old_len < sizeof(*item)) {
1758ea05e3aSAlexander Block 		btrfs_release_path(path);
1768ea05e3aSAlexander Block 		ret = btrfs_search_slot(trans, root, key, path,
1778ea05e3aSAlexander Block 				-1, 1);
178005d6427SDavid Sterba 		if (ret < 0) {
179005d6427SDavid Sterba 			btrfs_abort_transaction(trans, root, ret);
180005d6427SDavid Sterba 			goto out;
181005d6427SDavid Sterba 		}
182005d6427SDavid Sterba 
1838ea05e3aSAlexander Block 		ret = btrfs_del_item(trans, root, path);
184005d6427SDavid Sterba 		if (ret < 0) {
185005d6427SDavid Sterba 			btrfs_abort_transaction(trans, root, ret);
186005d6427SDavid Sterba 			goto out;
187005d6427SDavid Sterba 		}
1888ea05e3aSAlexander Block 		btrfs_release_path(path);
1898ea05e3aSAlexander Block 		ret = btrfs_insert_empty_item(trans, root, path,
1908ea05e3aSAlexander Block 				key, sizeof(*item));
191005d6427SDavid Sterba 		if (ret < 0) {
192005d6427SDavid Sterba 			btrfs_abort_transaction(trans, root, ret);
193005d6427SDavid Sterba 			goto out;
194005d6427SDavid Sterba 		}
1958ea05e3aSAlexander Block 		l = path->nodes[0];
1968ea05e3aSAlexander Block 		slot = path->slots[0];
1978ea05e3aSAlexander Block 		ptr = btrfs_item_ptr_offset(l, slot);
1988ea05e3aSAlexander Block 	}
1998ea05e3aSAlexander Block 
2008ea05e3aSAlexander Block 	/*
2018ea05e3aSAlexander Block 	 * Update generation_v2 so at the next mount we know the new root
2028ea05e3aSAlexander Block 	 * fields are valid.
2038ea05e3aSAlexander Block 	 */
2048ea05e3aSAlexander Block 	btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
2058ea05e3aSAlexander Block 
2065f39d397SChris Mason 	write_extent_buffer(l, item, ptr, sizeof(*item));
2075caf2a00SChris Mason 	btrfs_mark_buffer_dirty(path->nodes[0]);
2083768f368SChris Mason out:
2095caf2a00SChris Mason 	btrfs_free_path(path);
2103768f368SChris Mason 	return ret;
2113768f368SChris Mason }
2123768f368SChris Mason 
213d16cb050SJeff Mahoney int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
214d16cb050SJeff Mahoney 		      struct btrfs_key *key, struct btrfs_root_item *item)
2153768f368SChris Mason {
2168ea05e3aSAlexander Block 	/*
2178ea05e3aSAlexander Block 	 * Make sure generation v1 and v2 match. See update_root for details.
2188ea05e3aSAlexander Block 	 */
2198ea05e3aSAlexander Block 	btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
220d16cb050SJeff Mahoney 	return btrfs_insert_item(trans, root, key, item, sizeof(*item));
2213768f368SChris Mason }
2223768f368SChris Mason 
22376dda93cSYan, Zheng int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
22476dda93cSYan, Zheng {
22576dda93cSYan, Zheng 	struct extent_buffer *leaf;
22676dda93cSYan, Zheng 	struct btrfs_path *path;
22776dda93cSYan, Zheng 	struct btrfs_key key;
228d68fc57bSYan, Zheng 	struct btrfs_key root_key;
229d68fc57bSYan, Zheng 	struct btrfs_root *root;
23076dda93cSYan, Zheng 	int err = 0;
23176dda93cSYan, Zheng 	int ret;
23268a7342cSJosef Bacik 	bool can_recover = true;
23368a7342cSJosef Bacik 
23468a7342cSJosef Bacik 	if (tree_root->fs_info->sb->s_flags & MS_RDONLY)
23568a7342cSJosef Bacik 		can_recover = false;
23676dda93cSYan, Zheng 
23776dda93cSYan, Zheng 	path = btrfs_alloc_path();
23876dda93cSYan, Zheng 	if (!path)
23976dda93cSYan, Zheng 		return -ENOMEM;
24076dda93cSYan, Zheng 
24176dda93cSYan, Zheng 	key.objectid = BTRFS_ORPHAN_OBJECTID;
24276dda93cSYan, Zheng 	key.type = BTRFS_ORPHAN_ITEM_KEY;
24376dda93cSYan, Zheng 	key.offset = 0;
24476dda93cSYan, Zheng 
245d68fc57bSYan, Zheng 	root_key.type = BTRFS_ROOT_ITEM_KEY;
246d68fc57bSYan, Zheng 	root_key.offset = (u64)-1;
247d68fc57bSYan, Zheng 
24876dda93cSYan, Zheng 	while (1) {
24976dda93cSYan, Zheng 		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
25076dda93cSYan, Zheng 		if (ret < 0) {
25176dda93cSYan, Zheng 			err = ret;
25276dda93cSYan, Zheng 			break;
25376dda93cSYan, Zheng 		}
25476dda93cSYan, Zheng 
25576dda93cSYan, Zheng 		leaf = path->nodes[0];
25676dda93cSYan, Zheng 		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
25776dda93cSYan, Zheng 			ret = btrfs_next_leaf(tree_root, path);
25876dda93cSYan, Zheng 			if (ret < 0)
25976dda93cSYan, Zheng 				err = ret;
26076dda93cSYan, Zheng 			if (ret != 0)
26176dda93cSYan, Zheng 				break;
26276dda93cSYan, Zheng 			leaf = path->nodes[0];
26376dda93cSYan, Zheng 		}
26476dda93cSYan, Zheng 
26576dda93cSYan, Zheng 		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
266b3b4aa74SDavid Sterba 		btrfs_release_path(path);
26776dda93cSYan, Zheng 
26876dda93cSYan, Zheng 		if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
26976dda93cSYan, Zheng 		    key.type != BTRFS_ORPHAN_ITEM_KEY)
27076dda93cSYan, Zheng 			break;
27176dda93cSYan, Zheng 
272d68fc57bSYan, Zheng 		root_key.objectid = key.offset;
273d68fc57bSYan, Zheng 		key.offset++;
274d68fc57bSYan, Zheng 
275cb517eabSMiao Xie 		root = btrfs_read_fs_root(tree_root, &root_key);
276886322e8SSachin Kamat 		err = PTR_ERR_OR_ZERO(root);
27768a7342cSJosef Bacik 		if (err && err != -ENOENT) {
27876dda93cSYan, Zheng 			break;
27968a7342cSJosef Bacik 		} else if (err == -ENOENT) {
28068a7342cSJosef Bacik 			struct btrfs_trans_handle *trans;
28168a7342cSJosef Bacik 
28268a7342cSJosef Bacik 			btrfs_release_path(path);
28368a7342cSJosef Bacik 
28468a7342cSJosef Bacik 			trans = btrfs_join_transaction(tree_root);
28568a7342cSJosef Bacik 			if (IS_ERR(trans)) {
28668a7342cSJosef Bacik 				err = PTR_ERR(trans);
287a4553fefSAnand Jain 				btrfs_std_error(tree_root->fs_info, err,
28868a7342cSJosef Bacik 					    "Failed to start trans to delete "
28968a7342cSJosef Bacik 					    "orphan item");
29068a7342cSJosef Bacik 				break;
29168a7342cSJosef Bacik 			}
29268a7342cSJosef Bacik 			err = btrfs_del_orphan_item(trans, tree_root,
29368a7342cSJosef Bacik 						    root_key.objectid);
29468a7342cSJosef Bacik 			btrfs_end_transaction(trans, tree_root);
29568a7342cSJosef Bacik 			if (err) {
296a4553fefSAnand Jain 				btrfs_std_error(tree_root->fs_info, err,
29768a7342cSJosef Bacik 					    "Failed to delete root orphan "
29868a7342cSJosef Bacik 					    "item");
29968a7342cSJosef Bacik 				break;
30068a7342cSJosef Bacik 			}
30168a7342cSJosef Bacik 			continue;
30276dda93cSYan, Zheng 		}
30376dda93cSYan, Zheng 
304cb517eabSMiao Xie 		err = btrfs_init_fs_root(root);
305cb517eabSMiao Xie 		if (err) {
306cb517eabSMiao Xie 			btrfs_free_fs_root(root);
307cb517eabSMiao Xie 			break;
308cb517eabSMiao Xie 		}
309cb517eabSMiao Xie 
31027cdeb70SMiao Xie 		set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
311cb517eabSMiao Xie 
312cb517eabSMiao Xie 		err = btrfs_insert_fs_root(root->fs_info, root);
313909c3a22SFilipe Manana 		/*
314909c3a22SFilipe Manana 		 * The root might have been inserted already, as before we look
315909c3a22SFilipe Manana 		 * for orphan roots, log replay might have happened, which
316909c3a22SFilipe Manana 		 * triggers a transaction commit and qgroup accounting, which
317909c3a22SFilipe Manana 		 * in turn reads and inserts fs roots while doing backref
318909c3a22SFilipe Manana 		 * walking.
319909c3a22SFilipe Manana 		 */
320909c3a22SFilipe Manana 		if (err == -EEXIST)
321909c3a22SFilipe Manana 			err = 0;
322cb517eabSMiao Xie 		if (err) {
323cb517eabSMiao Xie 			btrfs_free_fs_root(root);
324d68fc57bSYan, Zheng 			break;
325d68fc57bSYan, Zheng 		}
32614927d95SMiao Xie 
32714927d95SMiao Xie 		if (btrfs_root_refs(&root->root_item) == 0)
32814927d95SMiao Xie 			btrfs_add_dead_root(root);
32976dda93cSYan, Zheng 	}
33076dda93cSYan, Zheng 
33176dda93cSYan, Zheng 	btrfs_free_path(path);
33276dda93cSYan, Zheng 	return err;
33376dda93cSYan, Zheng }
33476dda93cSYan, Zheng 
335d352ac68SChris Mason /* drop the root item for 'key' from 'root' */
336e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
337e089f05cSChris Mason 		   struct btrfs_key *key)
3383768f368SChris Mason {
3395caf2a00SChris Mason 	struct btrfs_path *path;
3403768f368SChris Mason 	int ret;
3413768f368SChris Mason 
3425caf2a00SChris Mason 	path = btrfs_alloc_path();
343db5b493aSTsutomu Itoh 	if (!path)
344db5b493aSTsutomu Itoh 		return -ENOMEM;
3455caf2a00SChris Mason 	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
3463768f368SChris Mason 	if (ret < 0)
3473768f368SChris Mason 		goto out;
348edbd8d4eSChris Mason 
3493768f368SChris Mason 	BUG_ON(ret != 0);
350c5739bbaSChris Mason 
3515caf2a00SChris Mason 	ret = btrfs_del_item(trans, root, path);
3523768f368SChris Mason out:
3535caf2a00SChris Mason 	btrfs_free_path(path);
3543768f368SChris Mason 	return ret;
3553768f368SChris Mason }
3560660b5afSChris Mason 
3570660b5afSChris Mason int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
3580660b5afSChris Mason 		       struct btrfs_root *tree_root,
3594df27c4dSYan, Zheng 		       u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
3604df27c4dSYan, Zheng 		       const char *name, int name_len)
3614df27c4dSYan, Zheng 
3620660b5afSChris Mason {
3630660b5afSChris Mason 	struct btrfs_path *path;
3644df27c4dSYan, Zheng 	struct btrfs_root_ref *ref;
3654df27c4dSYan, Zheng 	struct extent_buffer *leaf;
3664df27c4dSYan, Zheng 	struct btrfs_key key;
3674df27c4dSYan, Zheng 	unsigned long ptr;
3684df27c4dSYan, Zheng 	int err = 0;
3694df27c4dSYan, Zheng 	int ret;
3700660b5afSChris Mason 
3710660b5afSChris Mason 	path = btrfs_alloc_path();
3724df27c4dSYan, Zheng 	if (!path)
3734df27c4dSYan, Zheng 		return -ENOMEM;
3740660b5afSChris Mason 
3750660b5afSChris Mason 	key.objectid = root_id;
3764df27c4dSYan, Zheng 	key.type = BTRFS_ROOT_BACKREF_KEY;
3770660b5afSChris Mason 	key.offset = ref_id;
3784df27c4dSYan, Zheng again:
3790660b5afSChris Mason 	ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
3804df27c4dSYan, Zheng 	BUG_ON(ret < 0);
3814df27c4dSYan, Zheng 	if (ret == 0) {
3824df27c4dSYan, Zheng 		leaf = path->nodes[0];
3834df27c4dSYan, Zheng 		ref = btrfs_item_ptr(leaf, path->slots[0],
3844df27c4dSYan, Zheng 				     struct btrfs_root_ref);
3854df27c4dSYan, Zheng 
3864df27c4dSYan, Zheng 		WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
3874df27c4dSYan, Zheng 		WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
3884df27c4dSYan, Zheng 		ptr = (unsigned long)(ref + 1);
3894df27c4dSYan, Zheng 		WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
3904df27c4dSYan, Zheng 		*sequence = btrfs_root_ref_sequence(leaf, ref);
3910660b5afSChris Mason 
3920660b5afSChris Mason 		ret = btrfs_del_item(trans, tree_root, path);
39365a246c5STsutomu Itoh 		if (ret) {
39465a246c5STsutomu Itoh 			err = ret;
39565a246c5STsutomu Itoh 			goto out;
39665a246c5STsutomu Itoh 		}
3974df27c4dSYan, Zheng 	} else
3984df27c4dSYan, Zheng 		err = -ENOENT;
3994df27c4dSYan, Zheng 
4004df27c4dSYan, Zheng 	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
401b3b4aa74SDavid Sterba 		btrfs_release_path(path);
4024df27c4dSYan, Zheng 		key.objectid = ref_id;
4034df27c4dSYan, Zheng 		key.type = BTRFS_ROOT_REF_KEY;
4044df27c4dSYan, Zheng 		key.offset = root_id;
4054df27c4dSYan, Zheng 		goto again;
4064df27c4dSYan, Zheng 	}
4070660b5afSChris Mason 
40865a246c5STsutomu Itoh out:
4090660b5afSChris Mason 	btrfs_free_path(path);
4104df27c4dSYan, Zheng 	return err;
4110660b5afSChris Mason }
4120660b5afSChris Mason 
4130660b5afSChris Mason /*
4140660b5afSChris Mason  * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
4150660b5afSChris Mason  * or BTRFS_ROOT_BACKREF_KEY.
4160660b5afSChris Mason  *
4170660b5afSChris Mason  * The dirid, sequence, name and name_len refer to the directory entry
4180660b5afSChris Mason  * that is referencing the root.
4190660b5afSChris Mason  *
4200660b5afSChris Mason  * For a forward ref, the root_id is the id of the tree referencing
4210660b5afSChris Mason  * the root and ref_id is the id of the subvol  or snapshot.
4220660b5afSChris Mason  *
4230660b5afSChris Mason  * For a back ref the root_id is the id of the subvol or snapshot and
4240660b5afSChris Mason  * ref_id is the id of the tree referencing it.
42579787eaaSJeff Mahoney  *
42679787eaaSJeff Mahoney  * Will return 0, -ENOMEM, or anything from the CoW path
4270660b5afSChris Mason  */
4280660b5afSChris Mason int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
4290660b5afSChris Mason 		       struct btrfs_root *tree_root,
4304df27c4dSYan, Zheng 		       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
4310660b5afSChris Mason 		       const char *name, int name_len)
4320660b5afSChris Mason {
4330660b5afSChris Mason 	struct btrfs_key key;
4340660b5afSChris Mason 	int ret;
4350660b5afSChris Mason 	struct btrfs_path *path;
4360660b5afSChris Mason 	struct btrfs_root_ref *ref;
4370660b5afSChris Mason 	struct extent_buffer *leaf;
4380660b5afSChris Mason 	unsigned long ptr;
4390660b5afSChris Mason 
4400660b5afSChris Mason 	path = btrfs_alloc_path();
4414df27c4dSYan, Zheng 	if (!path)
4424df27c4dSYan, Zheng 		return -ENOMEM;
4430660b5afSChris Mason 
4440660b5afSChris Mason 	key.objectid = root_id;
4454df27c4dSYan, Zheng 	key.type = BTRFS_ROOT_BACKREF_KEY;
4460660b5afSChris Mason 	key.offset = ref_id;
4474df27c4dSYan, Zheng again:
4480660b5afSChris Mason 	ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
4490660b5afSChris Mason 				      sizeof(*ref) + name_len);
45079787eaaSJeff Mahoney 	if (ret) {
45179787eaaSJeff Mahoney 		btrfs_abort_transaction(trans, tree_root, ret);
45279787eaaSJeff Mahoney 		btrfs_free_path(path);
45379787eaaSJeff Mahoney 		return ret;
45479787eaaSJeff Mahoney 	}
4550660b5afSChris Mason 
4560660b5afSChris Mason 	leaf = path->nodes[0];
4570660b5afSChris Mason 	ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
4580660b5afSChris Mason 	btrfs_set_root_ref_dirid(leaf, ref, dirid);
4590660b5afSChris Mason 	btrfs_set_root_ref_sequence(leaf, ref, sequence);
4600660b5afSChris Mason 	btrfs_set_root_ref_name_len(leaf, ref, name_len);
4610660b5afSChris Mason 	ptr = (unsigned long)(ref + 1);
4620660b5afSChris Mason 	write_extent_buffer(leaf, name, ptr, name_len);
4630660b5afSChris Mason 	btrfs_mark_buffer_dirty(leaf);
4640660b5afSChris Mason 
4654df27c4dSYan, Zheng 	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
466b3b4aa74SDavid Sterba 		btrfs_release_path(path);
4674df27c4dSYan, Zheng 		key.objectid = ref_id;
4684df27c4dSYan, Zheng 		key.type = BTRFS_ROOT_REF_KEY;
4694df27c4dSYan, Zheng 		key.offset = root_id;
4704df27c4dSYan, Zheng 		goto again;
4714df27c4dSYan, Zheng 	}
4724df27c4dSYan, Zheng 
4730660b5afSChris Mason 	btrfs_free_path(path);
4744df27c4dSYan, Zheng 	return 0;
4750660b5afSChris Mason }
47608fe4db1SLi Zefan 
47708fe4db1SLi Zefan /*
47808fe4db1SLi Zefan  * Old btrfs forgets to init root_item->flags and root_item->byte_limit
47908fe4db1SLi Zefan  * for subvolumes. To work around this problem, we steal a bit from
48008fe4db1SLi Zefan  * root_item->inode_item->flags, and use it to indicate if those fields
48108fe4db1SLi Zefan  * have been properly initialized.
48208fe4db1SLi Zefan  */
48308fe4db1SLi Zefan void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
48408fe4db1SLi Zefan {
4853cae210fSQu Wenruo 	u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode);
48608fe4db1SLi Zefan 
48708fe4db1SLi Zefan 	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
48808fe4db1SLi Zefan 		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
4893cae210fSQu Wenruo 		btrfs_set_stack_inode_flags(&root_item->inode, inode_flags);
4903cae210fSQu Wenruo 		btrfs_set_root_flags(root_item, 0);
4913cae210fSQu Wenruo 		btrfs_set_root_limit(root_item, 0);
49208fe4db1SLi Zefan 	}
49308fe4db1SLi Zefan }
4948ea05e3aSAlexander Block 
4958ea05e3aSAlexander Block void btrfs_update_root_times(struct btrfs_trans_handle *trans,
4968ea05e3aSAlexander Block 			     struct btrfs_root *root)
4978ea05e3aSAlexander Block {
4988ea05e3aSAlexander Block 	struct btrfs_root_item *item = &root->root_item;
49904b285f3SDeepa Dinamani 	struct timespec ct = current_fs_time(root->fs_info->sb);
5008ea05e3aSAlexander Block 
5015f3ab90aSAnand Jain 	spin_lock(&root->root_item_lock);
5023cae210fSQu Wenruo 	btrfs_set_root_ctransid(item, trans->transid);
5033cae210fSQu Wenruo 	btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
5043cae210fSQu Wenruo 	btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);
5055f3ab90aSAnand Jain 	spin_unlock(&root->root_item_lock);
5068ea05e3aSAlexander Block }
507