xref: /linux/fs/btrfs/root-tree.c (revision bf5f32ecb6caac52b4d1c083251b3dd4f40a0b7a)
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 
193768f368SChris Mason #include "ctree.h"
205eda7b5eSChris Mason #include "transaction.h"
213768f368SChris Mason #include "disk-io.h"
223768f368SChris Mason #include "print-tree.h"
233768f368SChris Mason 
24bf4ef679SChris Mason /*
25d352ac68SChris Mason  * lookup the root with the highest offset for a given objectid.  The key we do
26d352ac68SChris Mason  * find is copied into 'key'.  If we find something return 0, otherwise 1, < 0
27d352ac68SChris Mason  * on error.
28d352ac68SChris Mason  */
293768f368SChris Mason int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
303768f368SChris Mason 			struct btrfs_root_item *item, struct btrfs_key *key)
313768f368SChris Mason {
325caf2a00SChris Mason 	struct btrfs_path *path;
333768f368SChris Mason 	struct btrfs_key search_key;
345f39d397SChris Mason 	struct btrfs_key found_key;
355f39d397SChris Mason 	struct extent_buffer *l;
363768f368SChris Mason 	int ret;
373768f368SChris Mason 	int slot;
383768f368SChris Mason 
393768f368SChris Mason 	search_key.objectid = objectid;
400660b5afSChris Mason 	search_key.type = BTRFS_ROOT_ITEM_KEY;
415eda7b5eSChris Mason 	search_key.offset = (u64)-1;
423768f368SChris Mason 
435caf2a00SChris Mason 	path = btrfs_alloc_path();
44db5b493aSTsutomu Itoh 	if (!path)
45db5b493aSTsutomu Itoh 		return -ENOMEM;
465caf2a00SChris Mason 	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
473768f368SChris Mason 	if (ret < 0)
483768f368SChris Mason 		goto out;
495f39d397SChris Mason 
503768f368SChris Mason 	BUG_ON(ret == 0);
5176dda93cSYan, Zheng 	if (path->slots[0] == 0) {
523768f368SChris Mason 		ret = 1;
533768f368SChris Mason 		goto out;
543768f368SChris Mason 	}
5576dda93cSYan, Zheng 	l = path->nodes[0];
5676dda93cSYan, Zheng 	slot = path->slots[0] - 1;
5776dda93cSYan, Zheng 	btrfs_item_key_to_cpu(l, &found_key, slot);
5876dda93cSYan, Zheng 	if (found_key.objectid != objectid ||
5976dda93cSYan, Zheng 	    found_key.type != BTRFS_ROOT_ITEM_KEY) {
6076dda93cSYan, Zheng 		ret = 1;
6176dda93cSYan, Zheng 		goto out;
6276dda93cSYan, Zheng 	}
6376dda93cSYan, Zheng 	if (item)
645f39d397SChris Mason 		read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot),
653768f368SChris Mason 				   sizeof(*item));
6676dda93cSYan, Zheng 	if (key)
675f39d397SChris Mason 		memcpy(key, &found_key, sizeof(found_key));
683768f368SChris Mason 	ret = 0;
693768f368SChris Mason out:
705caf2a00SChris Mason 	btrfs_free_path(path);
713768f368SChris Mason 	return ret;
723768f368SChris Mason }
733768f368SChris Mason 
74*bf5f32ecSMark Fasheh void btrfs_set_root_node(struct btrfs_root_item *item,
755d4f98a2SYan Zheng 			 struct extent_buffer *node)
765d4f98a2SYan Zheng {
775d4f98a2SYan Zheng 	btrfs_set_root_bytenr(item, node->start);
785d4f98a2SYan Zheng 	btrfs_set_root_level(item, btrfs_header_level(node));
795d4f98a2SYan Zheng 	btrfs_set_root_generation(item, btrfs_header_generation(node));
805d4f98a2SYan Zheng }
815d4f98a2SYan Zheng 
82d352ac68SChris Mason /*
83d352ac68SChris Mason  * copy the data in 'item' into the btree
84d352ac68SChris Mason  */
85e089f05cSChris Mason int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
86e089f05cSChris Mason 		      *root, struct btrfs_key *key, struct btrfs_root_item
87e089f05cSChris Mason 		      *item)
883768f368SChris Mason {
895caf2a00SChris Mason 	struct btrfs_path *path;
905f39d397SChris Mason 	struct extent_buffer *l;
913768f368SChris Mason 	int ret;
923768f368SChris Mason 	int slot;
935f39d397SChris Mason 	unsigned long ptr;
943768f368SChris Mason 
955caf2a00SChris Mason 	path = btrfs_alloc_path();
965caf2a00SChris Mason 	BUG_ON(!path);
975caf2a00SChris Mason 	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
983768f368SChris Mason 	if (ret < 0)
993768f368SChris Mason 		goto out;
100d6667462SChris Mason 
101d6667462SChris Mason 	if (ret != 0) {
102d6667462SChris Mason 		btrfs_print_leaf(root, path->nodes[0]);
103d397712bSChris Mason 		printk(KERN_CRIT "unable to update root key %llu %u %llu\n",
104d397712bSChris Mason 		       (unsigned long long)key->objectid, key->type,
105d397712bSChris Mason 		       (unsigned long long)key->offset);
106d6667462SChris Mason 		BUG_ON(1);
107d6667462SChris Mason 	}
108d6667462SChris Mason 
1095f39d397SChris Mason 	l = path->nodes[0];
1105caf2a00SChris Mason 	slot = path->slots[0];
1115f39d397SChris Mason 	ptr = btrfs_item_ptr_offset(l, slot);
1125f39d397SChris Mason 	write_extent_buffer(l, item, ptr, sizeof(*item));
1135caf2a00SChris Mason 	btrfs_mark_buffer_dirty(path->nodes[0]);
1143768f368SChris Mason out:
1155caf2a00SChris Mason 	btrfs_free_path(path);
1163768f368SChris Mason 	return ret;
1173768f368SChris Mason }
1183768f368SChris Mason 
119e089f05cSChris Mason int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
120e089f05cSChris Mason 		      *root, struct btrfs_key *key, struct btrfs_root_item
121e089f05cSChris Mason 		      *item)
1223768f368SChris Mason {
1233768f368SChris Mason 	int ret;
124e089f05cSChris Mason 	ret = btrfs_insert_item(trans, root, key, item, sizeof(*item));
1253768f368SChris Mason 	return ret;
1263768f368SChris Mason }
1273768f368SChris Mason 
128d352ac68SChris Mason /*
129d352ac68SChris Mason  * at mount time we want to find all the old transaction snapshots that were in
130d397712bSChris Mason  * the process of being deleted if we crashed.  This is any root item with an
131d397712bSChris Mason  * offset lower than the latest root.  They need to be queued for deletion to
132d397712bSChris Mason  * finish what was happening when we crashed.
133d352ac68SChris Mason  */
1345d4f98a2SYan Zheng int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
1355eda7b5eSChris Mason {
1365eda7b5eSChris Mason 	struct btrfs_root *dead_root;
1375eda7b5eSChris Mason 	struct btrfs_root_item *ri;
1385eda7b5eSChris Mason 	struct btrfs_key key;
139a7a16fd7SChris Mason 	struct btrfs_key found_key;
1405eda7b5eSChris Mason 	struct btrfs_path *path;
1415eda7b5eSChris Mason 	int ret;
1425eda7b5eSChris Mason 	u32 nritems;
1435f39d397SChris Mason 	struct extent_buffer *leaf;
1445eda7b5eSChris Mason 	int slot;
1455eda7b5eSChris Mason 
1465ce14bbcSChris Mason 	key.objectid = objectid;
1475eda7b5eSChris Mason 	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
1485eda7b5eSChris Mason 	key.offset = 0;
1495eda7b5eSChris Mason 	path = btrfs_alloc_path();
1505eda7b5eSChris Mason 	if (!path)
1515eda7b5eSChris Mason 		return -ENOMEM;
152a7a16fd7SChris Mason 
153a7a16fd7SChris Mason again:
1545eda7b5eSChris Mason 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1555eda7b5eSChris Mason 	if (ret < 0)
1565eda7b5eSChris Mason 		goto err;
1575eda7b5eSChris Mason 	while (1) {
1585f39d397SChris Mason 		leaf = path->nodes[0];
1595f39d397SChris Mason 		nritems = btrfs_header_nritems(leaf);
1605eda7b5eSChris Mason 		slot = path->slots[0];
1615eda7b5eSChris Mason 		if (slot >= nritems) {
1625eda7b5eSChris Mason 			ret = btrfs_next_leaf(root, path);
1635eda7b5eSChris Mason 			if (ret)
1645eda7b5eSChris Mason 				break;
1655f39d397SChris Mason 			leaf = path->nodes[0];
1665f39d397SChris Mason 			nritems = btrfs_header_nritems(leaf);
1675eda7b5eSChris Mason 			slot = path->slots[0];
1685eda7b5eSChris Mason 		}
1695f39d397SChris Mason 		btrfs_item_key_to_cpu(leaf, &key, slot);
1705eda7b5eSChris Mason 		if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
1715eda7b5eSChris Mason 			goto next;
1725ce14bbcSChris Mason 
1735ce14bbcSChris Mason 		if (key.objectid < objectid)
1745ce14bbcSChris Mason 			goto next;
1755ce14bbcSChris Mason 
1765ce14bbcSChris Mason 		if (key.objectid > objectid)
1775ce14bbcSChris Mason 			break;
1785ce14bbcSChris Mason 
1795eda7b5eSChris Mason 		ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
1805f39d397SChris Mason 		if (btrfs_disk_root_refs(leaf, ri) != 0)
1815eda7b5eSChris Mason 			goto next;
1825ce14bbcSChris Mason 
183a7a16fd7SChris Mason 		memcpy(&found_key, &key, sizeof(key));
184a7a16fd7SChris Mason 		key.offset++;
185b3b4aa74SDavid Sterba 		btrfs_release_path(path);
186e02119d5SChris Mason 		dead_root =
187e02119d5SChris Mason 			btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
188a7a16fd7SChris Mason 						    &found_key);
189a1f39630SAneesh 		if (IS_ERR(dead_root)) {
190a1f39630SAneesh 			ret = PTR_ERR(dead_root);
1915eda7b5eSChris Mason 			goto err;
1925eda7b5eSChris Mason 		}
1935ce14bbcSChris Mason 
1945d4f98a2SYan Zheng 		ret = btrfs_add_dead_root(dead_root);
1955eda7b5eSChris Mason 		if (ret)
1965eda7b5eSChris Mason 			goto err;
197a7a16fd7SChris Mason 		goto again;
1985eda7b5eSChris Mason next:
1995eda7b5eSChris Mason 		slot++;
2005eda7b5eSChris Mason 		path->slots[0]++;
2015eda7b5eSChris Mason 	}
2025eda7b5eSChris Mason 	ret = 0;
2035eda7b5eSChris Mason err:
2045eda7b5eSChris Mason 	btrfs_free_path(path);
2055eda7b5eSChris Mason 	return ret;
2065eda7b5eSChris Mason }
2075eda7b5eSChris Mason 
20876dda93cSYan, Zheng int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
20976dda93cSYan, Zheng {
21076dda93cSYan, Zheng 	struct extent_buffer *leaf;
21176dda93cSYan, Zheng 	struct btrfs_path *path;
21276dda93cSYan, Zheng 	struct btrfs_key key;
213d68fc57bSYan, Zheng 	struct btrfs_key root_key;
214d68fc57bSYan, Zheng 	struct btrfs_root *root;
21576dda93cSYan, Zheng 	int err = 0;
21676dda93cSYan, Zheng 	int ret;
21776dda93cSYan, Zheng 
21876dda93cSYan, Zheng 	path = btrfs_alloc_path();
21976dda93cSYan, Zheng 	if (!path)
22076dda93cSYan, Zheng 		return -ENOMEM;
22176dda93cSYan, Zheng 
22276dda93cSYan, Zheng 	key.objectid = BTRFS_ORPHAN_OBJECTID;
22376dda93cSYan, Zheng 	key.type = BTRFS_ORPHAN_ITEM_KEY;
22476dda93cSYan, Zheng 	key.offset = 0;
22576dda93cSYan, Zheng 
226d68fc57bSYan, Zheng 	root_key.type = BTRFS_ROOT_ITEM_KEY;
227d68fc57bSYan, Zheng 	root_key.offset = (u64)-1;
228d68fc57bSYan, Zheng 
22976dda93cSYan, Zheng 	while (1) {
23076dda93cSYan, Zheng 		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
23176dda93cSYan, Zheng 		if (ret < 0) {
23276dda93cSYan, Zheng 			err = ret;
23376dda93cSYan, Zheng 			break;
23476dda93cSYan, Zheng 		}
23576dda93cSYan, Zheng 
23676dda93cSYan, Zheng 		leaf = path->nodes[0];
23776dda93cSYan, Zheng 		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
23876dda93cSYan, Zheng 			ret = btrfs_next_leaf(tree_root, path);
23976dda93cSYan, Zheng 			if (ret < 0)
24076dda93cSYan, Zheng 				err = ret;
24176dda93cSYan, Zheng 			if (ret != 0)
24276dda93cSYan, Zheng 				break;
24376dda93cSYan, Zheng 			leaf = path->nodes[0];
24476dda93cSYan, Zheng 		}
24576dda93cSYan, Zheng 
24676dda93cSYan, Zheng 		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
247b3b4aa74SDavid Sterba 		btrfs_release_path(path);
24876dda93cSYan, Zheng 
24976dda93cSYan, Zheng 		if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
25076dda93cSYan, Zheng 		    key.type != BTRFS_ORPHAN_ITEM_KEY)
25176dda93cSYan, Zheng 			break;
25276dda93cSYan, Zheng 
253d68fc57bSYan, Zheng 		root_key.objectid = key.offset;
254d68fc57bSYan, Zheng 		key.offset++;
255d68fc57bSYan, Zheng 
256d68fc57bSYan, Zheng 		root = btrfs_read_fs_root_no_name(tree_root->fs_info,
257d68fc57bSYan, Zheng 						  &root_key);
258d68fc57bSYan, Zheng 		if (!IS_ERR(root))
259d68fc57bSYan, Zheng 			continue;
260d68fc57bSYan, Zheng 
261d68fc57bSYan, Zheng 		ret = PTR_ERR(root);
262d68fc57bSYan, Zheng 		if (ret != -ENOENT) {
26376dda93cSYan, Zheng 			err = ret;
26476dda93cSYan, Zheng 			break;
26576dda93cSYan, Zheng 		}
26676dda93cSYan, Zheng 
267d68fc57bSYan, Zheng 		ret = btrfs_find_dead_roots(tree_root, root_key.objectid);
268d68fc57bSYan, Zheng 		if (ret) {
269d68fc57bSYan, Zheng 			err = ret;
270d68fc57bSYan, Zheng 			break;
271d68fc57bSYan, Zheng 		}
27276dda93cSYan, Zheng 	}
27376dda93cSYan, Zheng 
27476dda93cSYan, Zheng 	btrfs_free_path(path);
27576dda93cSYan, Zheng 	return err;
27676dda93cSYan, Zheng }
27776dda93cSYan, Zheng 
278d352ac68SChris Mason /* drop the root item for 'key' from 'root' */
279e089f05cSChris Mason int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
280e089f05cSChris Mason 		   struct btrfs_key *key)
2813768f368SChris Mason {
2825caf2a00SChris Mason 	struct btrfs_path *path;
2833768f368SChris Mason 	int ret;
284c5739bbaSChris Mason 	struct btrfs_root_item *ri;
2855f39d397SChris Mason 	struct extent_buffer *leaf;
2863768f368SChris Mason 
2875caf2a00SChris Mason 	path = btrfs_alloc_path();
288db5b493aSTsutomu Itoh 	if (!path)
289db5b493aSTsutomu Itoh 		return -ENOMEM;
2905caf2a00SChris Mason 	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
2913768f368SChris Mason 	if (ret < 0)
2923768f368SChris Mason 		goto out;
293edbd8d4eSChris Mason 
2943768f368SChris Mason 	BUG_ON(ret != 0);
2955f39d397SChris Mason 	leaf = path->nodes[0];
2965f39d397SChris Mason 	ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
297c5739bbaSChris Mason 
2985caf2a00SChris Mason 	ret = btrfs_del_item(trans, root, path);
2993768f368SChris Mason out:
3005caf2a00SChris Mason 	btrfs_free_path(path);
3013768f368SChris Mason 	return ret;
3023768f368SChris Mason }
3030660b5afSChris Mason 
3040660b5afSChris Mason int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
3050660b5afSChris Mason 		       struct btrfs_root *tree_root,
3064df27c4dSYan, Zheng 		       u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
3074df27c4dSYan, Zheng 		       const char *name, int name_len)
3084df27c4dSYan, Zheng 
3090660b5afSChris Mason {
3100660b5afSChris Mason 	struct btrfs_path *path;
3114df27c4dSYan, Zheng 	struct btrfs_root_ref *ref;
3124df27c4dSYan, Zheng 	struct extent_buffer *leaf;
3134df27c4dSYan, Zheng 	struct btrfs_key key;
3144df27c4dSYan, Zheng 	unsigned long ptr;
3154df27c4dSYan, Zheng 	int err = 0;
3164df27c4dSYan, Zheng 	int ret;
3170660b5afSChris Mason 
3180660b5afSChris Mason 	path = btrfs_alloc_path();
3194df27c4dSYan, Zheng 	if (!path)
3204df27c4dSYan, Zheng 		return -ENOMEM;
3210660b5afSChris Mason 
3220660b5afSChris Mason 	key.objectid = root_id;
3234df27c4dSYan, Zheng 	key.type = BTRFS_ROOT_BACKREF_KEY;
3240660b5afSChris Mason 	key.offset = ref_id;
3254df27c4dSYan, Zheng again:
3260660b5afSChris Mason 	ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
3274df27c4dSYan, Zheng 	BUG_ON(ret < 0);
3284df27c4dSYan, Zheng 	if (ret == 0) {
3294df27c4dSYan, Zheng 		leaf = path->nodes[0];
3304df27c4dSYan, Zheng 		ref = btrfs_item_ptr(leaf, path->slots[0],
3314df27c4dSYan, Zheng 				     struct btrfs_root_ref);
3324df27c4dSYan, Zheng 
3334df27c4dSYan, Zheng 		WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
3344df27c4dSYan, Zheng 		WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
3354df27c4dSYan, Zheng 		ptr = (unsigned long)(ref + 1);
3364df27c4dSYan, Zheng 		WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
3374df27c4dSYan, Zheng 		*sequence = btrfs_root_ref_sequence(leaf, ref);
3380660b5afSChris Mason 
3390660b5afSChris Mason 		ret = btrfs_del_item(trans, tree_root, path);
34065a246c5STsutomu Itoh 		if (ret) {
34165a246c5STsutomu Itoh 			err = ret;
34265a246c5STsutomu Itoh 			goto out;
34365a246c5STsutomu Itoh 		}
3444df27c4dSYan, Zheng 	} else
3454df27c4dSYan, Zheng 		err = -ENOENT;
3464df27c4dSYan, Zheng 
3474df27c4dSYan, Zheng 	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
348b3b4aa74SDavid Sterba 		btrfs_release_path(path);
3494df27c4dSYan, Zheng 		key.objectid = ref_id;
3504df27c4dSYan, Zheng 		key.type = BTRFS_ROOT_REF_KEY;
3514df27c4dSYan, Zheng 		key.offset = root_id;
3524df27c4dSYan, Zheng 		goto again;
3534df27c4dSYan, Zheng 	}
3540660b5afSChris Mason 
35565a246c5STsutomu Itoh out:
3560660b5afSChris Mason 	btrfs_free_path(path);
3574df27c4dSYan, Zheng 	return err;
3580660b5afSChris Mason }
3590660b5afSChris Mason 
360ea9e8b11SChris Mason int btrfs_find_root_ref(struct btrfs_root *tree_root,
361ea9e8b11SChris Mason 		   struct btrfs_path *path,
362ea9e8b11SChris Mason 		   u64 root_id, u64 ref_id)
363ea9e8b11SChris Mason {
364ea9e8b11SChris Mason 	struct btrfs_key key;
365ea9e8b11SChris Mason 	int ret;
366ea9e8b11SChris Mason 
367ea9e8b11SChris Mason 	key.objectid = root_id;
368ea9e8b11SChris Mason 	key.type = BTRFS_ROOT_REF_KEY;
369ea9e8b11SChris Mason 	key.offset = ref_id;
370ea9e8b11SChris Mason 
371ea9e8b11SChris Mason 	ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
372ea9e8b11SChris Mason 	return ret;
373ea9e8b11SChris Mason }
374ea9e8b11SChris Mason 
3750660b5afSChris Mason /*
3760660b5afSChris Mason  * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
3770660b5afSChris Mason  * or BTRFS_ROOT_BACKREF_KEY.
3780660b5afSChris Mason  *
3790660b5afSChris Mason  * The dirid, sequence, name and name_len refer to the directory entry
3800660b5afSChris Mason  * that is referencing the root.
3810660b5afSChris Mason  *
3820660b5afSChris Mason  * For a forward ref, the root_id is the id of the tree referencing
3830660b5afSChris Mason  * the root and ref_id is the id of the subvol  or snapshot.
3840660b5afSChris Mason  *
3850660b5afSChris Mason  * For a back ref the root_id is the id of the subvol or snapshot and
3860660b5afSChris Mason  * ref_id is the id of the tree referencing it.
3870660b5afSChris Mason  */
3880660b5afSChris Mason int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
3890660b5afSChris Mason 		       struct btrfs_root *tree_root,
3904df27c4dSYan, Zheng 		       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
3910660b5afSChris Mason 		       const char *name, int name_len)
3920660b5afSChris Mason {
3930660b5afSChris Mason 	struct btrfs_key key;
3940660b5afSChris Mason 	int ret;
3950660b5afSChris Mason 	struct btrfs_path *path;
3960660b5afSChris Mason 	struct btrfs_root_ref *ref;
3970660b5afSChris Mason 	struct extent_buffer *leaf;
3980660b5afSChris Mason 	unsigned long ptr;
3990660b5afSChris Mason 
4000660b5afSChris Mason 	path = btrfs_alloc_path();
4014df27c4dSYan, Zheng 	if (!path)
4024df27c4dSYan, Zheng 		return -ENOMEM;
4030660b5afSChris Mason 
4040660b5afSChris Mason 	key.objectid = root_id;
4054df27c4dSYan, Zheng 	key.type = BTRFS_ROOT_BACKREF_KEY;
4060660b5afSChris Mason 	key.offset = ref_id;
4074df27c4dSYan, Zheng again:
4080660b5afSChris Mason 	ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
4090660b5afSChris Mason 				      sizeof(*ref) + name_len);
4100660b5afSChris Mason 	BUG_ON(ret);
4110660b5afSChris Mason 
4120660b5afSChris Mason 	leaf = path->nodes[0];
4130660b5afSChris Mason 	ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
4140660b5afSChris Mason 	btrfs_set_root_ref_dirid(leaf, ref, dirid);
4150660b5afSChris Mason 	btrfs_set_root_ref_sequence(leaf, ref, sequence);
4160660b5afSChris Mason 	btrfs_set_root_ref_name_len(leaf, ref, name_len);
4170660b5afSChris Mason 	ptr = (unsigned long)(ref + 1);
4180660b5afSChris Mason 	write_extent_buffer(leaf, name, ptr, name_len);
4190660b5afSChris Mason 	btrfs_mark_buffer_dirty(leaf);
4200660b5afSChris Mason 
4214df27c4dSYan, Zheng 	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
422b3b4aa74SDavid Sterba 		btrfs_release_path(path);
4234df27c4dSYan, Zheng 		key.objectid = ref_id;
4244df27c4dSYan, Zheng 		key.type = BTRFS_ROOT_REF_KEY;
4254df27c4dSYan, Zheng 		key.offset = root_id;
4264df27c4dSYan, Zheng 		goto again;
4274df27c4dSYan, Zheng 	}
4284df27c4dSYan, Zheng 
4290660b5afSChris Mason 	btrfs_free_path(path);
4304df27c4dSYan, Zheng 	return 0;
4310660b5afSChris Mason }
43208fe4db1SLi Zefan 
43308fe4db1SLi Zefan /*
43408fe4db1SLi Zefan  * Old btrfs forgets to init root_item->flags and root_item->byte_limit
43508fe4db1SLi Zefan  * for subvolumes. To work around this problem, we steal a bit from
43608fe4db1SLi Zefan  * root_item->inode_item->flags, and use it to indicate if those fields
43708fe4db1SLi Zefan  * have been properly initialized.
43808fe4db1SLi Zefan  */
43908fe4db1SLi Zefan void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
44008fe4db1SLi Zefan {
44108fe4db1SLi Zefan 	u64 inode_flags = le64_to_cpu(root_item->inode.flags);
44208fe4db1SLi Zefan 
44308fe4db1SLi Zefan 	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
44408fe4db1SLi Zefan 		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
44508fe4db1SLi Zefan 		root_item->inode.flags = cpu_to_le64(inode_flags);
44608fe4db1SLi Zefan 		root_item->flags = 0;
44708fe4db1SLi Zefan 		root_item->byte_limit = 0;
44808fe4db1SLi Zefan 	}
44908fe4db1SLi Zefan }
450