xref: /openbmc/linux/fs/btrfs/disk-io.c (revision 2619ba1f)
1e20d96d6SChris Mason #include <linux/module.h>
2e20d96d6SChris Mason #include <linux/fs.h>
3d98237b3SChris Mason #include <linux/blkdev.h>
487cbda5cSChris Mason #include <linux/crypto.h>
587cbda5cSChris Mason #include <linux/scatterlist.h>
622b0ebdaSChris Mason #include <linux/swap.h>
70f7d52f4SChris Mason #include <linux/radix-tree.h>
8eb60ceacSChris Mason #include "ctree.h"
9eb60ceacSChris Mason #include "disk-io.h"
10e089f05cSChris Mason #include "transaction.h"
110f7d52f4SChris Mason #include "btrfs_inode.h"
12eb60ceacSChris Mason 
13e20d96d6SChris Mason static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf)
14eb60ceacSChris Mason {
15e20d96d6SChris Mason 	struct btrfs_node *node = btrfs_buffer_node(buf);
16d98237b3SChris Mason 	if (buf->b_blocknr != btrfs_header_blocknr(&node->header)) {
179a8dd150SChris Mason 		BUG();
18d98237b3SChris Mason 	}
199a8dd150SChris Mason 	return 0;
20eb60ceacSChris Mason }
21eb60ceacSChris Mason 
22d98237b3SChris Mason struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr)
23ed2ff2cbSChris Mason {
24d98237b3SChris Mason 	struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
25d98237b3SChris Mason 	int blockbits = root->fs_info->sb->s_blocksize_bits;
26d98237b3SChris Mason 	unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits);
27d98237b3SChris Mason 	struct page *page;
28d98237b3SChris Mason 	struct buffer_head *bh;
29d98237b3SChris Mason 	struct buffer_head *head;
30d98237b3SChris Mason 	struct buffer_head *ret = NULL;
31d98237b3SChris Mason 
322c90e5d6SChris Mason 
33d98237b3SChris Mason 	page = find_lock_page(mapping, index);
34d98237b3SChris Mason 	if (!page)
35d98237b3SChris Mason 		return NULL;
36d98237b3SChris Mason 
37d98237b3SChris Mason 	if (!page_has_buffers(page))
38d98237b3SChris Mason 		goto out_unlock;
39d98237b3SChris Mason 
40d98237b3SChris Mason 	head = page_buffers(page);
41d98237b3SChris Mason 	bh = head;
42d98237b3SChris Mason 	do {
43d98237b3SChris Mason 		if (buffer_mapped(bh) && bh->b_blocknr == blocknr) {
44d98237b3SChris Mason 			ret = bh;
45d98237b3SChris Mason 			get_bh(bh);
46d98237b3SChris Mason 			goto out_unlock;
47d98237b3SChris Mason 		}
48d98237b3SChris Mason 		bh = bh->b_this_page;
49d98237b3SChris Mason 	} while (bh != head);
50d98237b3SChris Mason out_unlock:
51d98237b3SChris Mason 	unlock_page(page);
52d6025579SChris Mason 	if (ret) {
5322b0ebdaSChris Mason 		touch_buffer(ret);
54d6025579SChris Mason 	}
55d98237b3SChris Mason 	page_cache_release(page);
56d98237b3SChris Mason 	return ret;
57ed2ff2cbSChris Mason }
58ed2ff2cbSChris Mason 
59d98237b3SChris Mason struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root,
60d98237b3SChris Mason 						 u64 blocknr)
61eb60ceacSChris Mason {
62d98237b3SChris Mason 	struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
63d98237b3SChris Mason 	int blockbits = root->fs_info->sb->s_blocksize_bits;
64d98237b3SChris Mason 	unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits);
65d98237b3SChris Mason 	struct page *page;
66d98237b3SChris Mason 	struct buffer_head *bh;
67d98237b3SChris Mason 	struct buffer_head *head;
68d98237b3SChris Mason 	struct buffer_head *ret = NULL;
69d98237b3SChris Mason 	u64 first_block = index << (PAGE_CACHE_SHIFT - blockbits);
7022b0ebdaSChris Mason 
71d98237b3SChris Mason 	page = grab_cache_page(mapping, index);
72d98237b3SChris Mason 	if (!page)
73d98237b3SChris Mason 		return NULL;
74d98237b3SChris Mason 
75d98237b3SChris Mason 	if (!page_has_buffers(page))
76d98237b3SChris Mason 		create_empty_buffers(page, root->fs_info->sb->s_blocksize, 0);
77d98237b3SChris Mason 	head = page_buffers(page);
78d98237b3SChris Mason 	bh = head;
79d98237b3SChris Mason 	do {
80d98237b3SChris Mason 		if (!buffer_mapped(bh)) {
81d98237b3SChris Mason 			bh->b_bdev = root->fs_info->sb->s_bdev;
82d98237b3SChris Mason 			bh->b_blocknr = first_block;
83d98237b3SChris Mason 			set_buffer_mapped(bh);
84e20d96d6SChris Mason 		}
85d98237b3SChris Mason 		if (bh->b_blocknr == blocknr) {
86d98237b3SChris Mason 			ret = bh;
87d98237b3SChris Mason 			get_bh(bh);
88d98237b3SChris Mason 			goto out_unlock;
89d98237b3SChris Mason 		}
90d98237b3SChris Mason 		bh = bh->b_this_page;
91d98237b3SChris Mason 		first_block++;
92d98237b3SChris Mason 	} while (bh != head);
93d98237b3SChris Mason out_unlock:
94d98237b3SChris Mason 	unlock_page(page);
9522b0ebdaSChris Mason 	if (ret)
9622b0ebdaSChris Mason 		touch_buffer(ret);
97d98237b3SChris Mason 	page_cache_release(page);
98d98237b3SChris Mason 	return ret;
99d98237b3SChris Mason }
100d98237b3SChris Mason 
101d98237b3SChris Mason static sector_t max_block(struct block_device *bdev)
102d98237b3SChris Mason {
103d98237b3SChris Mason 	sector_t retval = ~((sector_t)0);
104d98237b3SChris Mason 	loff_t sz = i_size_read(bdev->bd_inode);
105d98237b3SChris Mason 
106d98237b3SChris Mason 	if (sz) {
107d98237b3SChris Mason 		unsigned int size = block_size(bdev);
108d98237b3SChris Mason 		unsigned int sizebits = blksize_bits(size);
109d98237b3SChris Mason 		retval = (sz >> sizebits);
110d98237b3SChris Mason 	}
111d98237b3SChris Mason 	return retval;
112d98237b3SChris Mason }
113d98237b3SChris Mason 
114d98237b3SChris Mason static int btree_get_block(struct inode *inode, sector_t iblock,
115d98237b3SChris Mason 			   struct buffer_head *bh, int create)
116d98237b3SChris Mason {
117d98237b3SChris Mason 	if (iblock >= max_block(inode->i_sb->s_bdev)) {
118d98237b3SChris Mason 		if (create)
119d98237b3SChris Mason 			return -EIO;
120d98237b3SChris Mason 
121d98237b3SChris Mason 		/*
122d98237b3SChris Mason 		 * for reads, we're just trying to fill a partial page.
123d98237b3SChris Mason 		 * return a hole, they will have to call get_block again
124d98237b3SChris Mason 		 * before they can fill it, and they will get -EIO at that
125d98237b3SChris Mason 		 * time
126d98237b3SChris Mason 		 */
127d98237b3SChris Mason 		return 0;
128d98237b3SChris Mason 	}
129d98237b3SChris Mason 	bh->b_bdev = inode->i_sb->s_bdev;
130d98237b3SChris Mason 	bh->b_blocknr = iblock;
131d98237b3SChris Mason 	set_buffer_mapped(bh);
132d98237b3SChris Mason 	return 0;
133d98237b3SChris Mason }
134d98237b3SChris Mason 
135f254e52cSChris Mason int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
136f254e52cSChris Mason 		    char *result)
13787cbda5cSChris Mason {
13887cbda5cSChris Mason 	struct scatterlist sg;
13987cbda5cSChris Mason 	struct crypto_hash *tfm = root->fs_info->hash_tfm;
14087cbda5cSChris Mason 	struct hash_desc desc;
14187cbda5cSChris Mason 	int ret;
14287cbda5cSChris Mason 
14387cbda5cSChris Mason 	desc.tfm = tfm;
14487cbda5cSChris Mason 	desc.flags = 0;
145f254e52cSChris Mason 	sg_init_one(&sg, data, len);
14687cbda5cSChris Mason 	spin_lock(&root->fs_info->hash_lock);
14722b0ebdaSChris Mason 	ret = crypto_hash_digest(&desc, &sg, 1, result);
14887cbda5cSChris Mason 	spin_unlock(&root->fs_info->hash_lock);
14987cbda5cSChris Mason 	if (ret) {
15087cbda5cSChris Mason 		printk("sha256 digest failed\n");
15187cbda5cSChris Mason 	}
152f254e52cSChris Mason 	return ret;
153f254e52cSChris Mason }
154f254e52cSChris Mason static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh,
155f254e52cSChris Mason 			   int verify)
156f254e52cSChris Mason {
157f254e52cSChris Mason 	char result[BTRFS_CSUM_SIZE];
158f254e52cSChris Mason 	int ret;
159f254e52cSChris Mason 	struct btrfs_node *node;
160f254e52cSChris Mason 
161f254e52cSChris Mason 	ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE,
162f254e52cSChris Mason 			      bh->b_size - BTRFS_CSUM_SIZE, result);
163f254e52cSChris Mason 	if (ret)
164f254e52cSChris Mason 		return ret;
16587cbda5cSChris Mason 	if (verify) {
166f254e52cSChris Mason 		if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) {
167f254e52cSChris Mason 			printk("checksum verify failed on %lu\n",
168f254e52cSChris Mason 			       bh->b_blocknr);
169f254e52cSChris Mason 			return 1;
170f254e52cSChris Mason 		}
171f254e52cSChris Mason 	} else {
172f254e52cSChris Mason 		node = btrfs_buffer_node(bh);
17322b0ebdaSChris Mason 		memcpy(node->header.csum, result, BTRFS_CSUM_SIZE);
174f254e52cSChris Mason 	}
17587cbda5cSChris Mason 	return 0;
17687cbda5cSChris Mason }
17787cbda5cSChris Mason 
178d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc)
179d98237b3SChris Mason {
18087cbda5cSChris Mason 	struct buffer_head *bh;
1810f7d52f4SChris Mason 	struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
18287cbda5cSChris Mason 	struct buffer_head *head;
18387cbda5cSChris Mason 	if (!page_has_buffers(page)) {
18487cbda5cSChris Mason 		create_empty_buffers(page, root->fs_info->sb->s_blocksize,
18587cbda5cSChris Mason 					(1 << BH_Dirty)|(1 << BH_Uptodate));
18687cbda5cSChris Mason 	}
18787cbda5cSChris Mason 	head = page_buffers(page);
18887cbda5cSChris Mason 	bh = head;
18987cbda5cSChris Mason 	do {
19087cbda5cSChris Mason 		if (buffer_dirty(bh))
19187cbda5cSChris Mason 			csum_tree_block(root, bh, 0);
19287cbda5cSChris Mason 		bh = bh->b_this_page;
19387cbda5cSChris Mason 	} while (bh != head);
194d98237b3SChris Mason 	return block_write_full_page(page, btree_get_block, wbc);
195d98237b3SChris Mason }
196d98237b3SChris Mason 
197d98237b3SChris Mason static int btree_readpage(struct file * file, struct page * page)
198d98237b3SChris Mason {
199d98237b3SChris Mason 	return block_read_full_page(page, btree_get_block);
200d98237b3SChris Mason }
201d98237b3SChris Mason 
202d98237b3SChris Mason static struct address_space_operations btree_aops = {
203d98237b3SChris Mason 	.readpage	= btree_readpage,
204d98237b3SChris Mason 	.writepage	= btree_writepage,
205d98237b3SChris Mason 	.sync_page	= block_sync_page,
206d98237b3SChris Mason };
207123abc88SChris Mason 
208e20d96d6SChris Mason struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
209e20d96d6SChris Mason {
210d98237b3SChris Mason 	struct buffer_head *bh = NULL;
211e20d96d6SChris Mason 
212d98237b3SChris Mason 	bh = btrfs_find_create_tree_block(root, blocknr);
213d98237b3SChris Mason 	if (!bh)
214d98237b3SChris Mason 		return bh;
2159d64272cSChris Mason 	if (buffer_uptodate(bh))
2169d64272cSChris Mason 		goto uptodate;
217d98237b3SChris Mason 	lock_buffer(bh);
218d98237b3SChris Mason 	if (!buffer_uptodate(bh)) {
219d98237b3SChris Mason 		get_bh(bh);
220d98237b3SChris Mason 		bh->b_end_io = end_buffer_read_sync;
221d98237b3SChris Mason 		submit_bh(READ, bh);
222d98237b3SChris Mason 		wait_on_buffer(bh);
223d98237b3SChris Mason 		if (!buffer_uptodate(bh))
224d98237b3SChris Mason 			goto fail;
22587cbda5cSChris Mason 		csum_tree_block(root, bh, 1);
226d98237b3SChris Mason 	} else {
227d98237b3SChris Mason 		unlock_buffer(bh);
228d98237b3SChris Mason 	}
2299d64272cSChris Mason uptodate:
230d98237b3SChris Mason 	if (check_tree_block(root, bh))
231cfaa7295SChris Mason 		BUG();
232d98237b3SChris Mason 	return bh;
233d98237b3SChris Mason fail:
234d98237b3SChris Mason 	brelse(bh);
235d98237b3SChris Mason 	return NULL;
236eb60ceacSChris Mason }
237eb60ceacSChris Mason 
238e089f05cSChris Mason int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
239e20d96d6SChris Mason 		     struct buffer_head *buf)
240ed2ff2cbSChris Mason {
241d6025579SChris Mason 	WARN_ON(atomic_read(&buf->b_count) == 0);
242e20d96d6SChris Mason 	mark_buffer_dirty(buf);
243ed2ff2cbSChris Mason 	return 0;
244ed2ff2cbSChris Mason }
245ed2ff2cbSChris Mason 
246e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
247e20d96d6SChris Mason 		     struct buffer_head *buf)
248ed2ff2cbSChris Mason {
249d6025579SChris Mason 	WARN_ON(atomic_read(&buf->b_count) == 0);
250e20d96d6SChris Mason 	clear_buffer_dirty(buf);
251ed2ff2cbSChris Mason 	return 0;
252ed2ff2cbSChris Mason }
253ed2ff2cbSChris Mason 
2542c90e5d6SChris Mason static int __setup_root(int blocksize,
2559f5fae2fSChris Mason 			struct btrfs_root *root,
2569f5fae2fSChris Mason 			struct btrfs_fs_info *fs_info,
257e20d96d6SChris Mason 			u64 objectid)
258d97e63b6SChris Mason {
259cfaa7295SChris Mason 	root->node = NULL;
2600f7d52f4SChris Mason 	root->inode = NULL;
261a28ec197SChris Mason 	root->commit_root = NULL;
2622c90e5d6SChris Mason 	root->blocksize = blocksize;
263123abc88SChris Mason 	root->ref_cows = 0;
2649f5fae2fSChris Mason 	root->fs_info = fs_info;
2650f7d52f4SChris Mason 	root->objectid = objectid;
2660f7d52f4SChris Mason 	root->last_trans = 0;
2671b05da2eSChris Mason 	root->highest_inode = 0;
2681b05da2eSChris Mason 	root->last_inode_alloc = 0;
2693768f368SChris Mason 	memset(&root->root_key, 0, sizeof(root->root_key));
2703768f368SChris Mason 	memset(&root->root_item, 0, sizeof(root->root_item));
2713768f368SChris Mason 	return 0;
2723768f368SChris Mason }
2733768f368SChris Mason 
2742c90e5d6SChris Mason static int find_and_setup_root(int blocksize,
2759f5fae2fSChris Mason 			       struct btrfs_root *tree_root,
2769f5fae2fSChris Mason 			       struct btrfs_fs_info *fs_info,
2779f5fae2fSChris Mason 			       u64 objectid,
278e20d96d6SChris Mason 			       struct btrfs_root *root)
2793768f368SChris Mason {
2803768f368SChris Mason 	int ret;
2813768f368SChris Mason 
2822c90e5d6SChris Mason 	__setup_root(blocksize, root, fs_info, objectid);
2833768f368SChris Mason 	ret = btrfs_find_last_root(tree_root, objectid,
2843768f368SChris Mason 				   &root->root_item, &root->root_key);
2853768f368SChris Mason 	BUG_ON(ret);
2863768f368SChris Mason 
2873768f368SChris Mason 	root->node = read_tree_block(root,
2883768f368SChris Mason 				     btrfs_root_blocknr(&root->root_item));
2893768f368SChris Mason 	BUG_ON(!root->node);
290d97e63b6SChris Mason 	return 0;
291d97e63b6SChris Mason }
292d97e63b6SChris Mason 
2930f7d52f4SChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
2940f7d52f4SChris Mason 				      struct btrfs_key *location)
2950f7d52f4SChris Mason {
2960f7d52f4SChris Mason 	struct btrfs_root *root;
2970f7d52f4SChris Mason 	struct btrfs_root *tree_root = fs_info->tree_root;
2980f7d52f4SChris Mason 	struct btrfs_path *path;
2990f7d52f4SChris Mason 	struct btrfs_leaf *l;
3001b05da2eSChris Mason 	u64 highest_inode;
3010f7d52f4SChris Mason 	int ret = 0;
3020f7d52f4SChris Mason 
3030f7d52f4SChris Mason printk("read_fs_root looking for %Lu %Lu %u\n", location->objectid, location->offset, location->flags);
3042619ba1fSChris Mason 	root = radix_tree_lookup(&fs_info->fs_roots_radix,
3052619ba1fSChris Mason 				 (unsigned long)location->objectid);
3062619ba1fSChris Mason 	if (root) {
3072619ba1fSChris Mason printk("found %p in cache\n", root);
3082619ba1fSChris Mason 		return root;
3092619ba1fSChris Mason 	}
3100f7d52f4SChris Mason 	root = kmalloc(sizeof(*root), GFP_NOFS);
3110f7d52f4SChris Mason 	if (!root) {
3120f7d52f4SChris Mason printk("failed1\n");
3130f7d52f4SChris Mason 		return ERR_PTR(-ENOMEM);
3140f7d52f4SChris Mason 	}
3150f7d52f4SChris Mason 	if (location->offset == (u64)-1) {
3160f7d52f4SChris Mason 		ret = find_and_setup_root(fs_info->sb->s_blocksize,
3170f7d52f4SChris Mason 					  fs_info->tree_root, fs_info,
3180f7d52f4SChris Mason 					  location->objectid, root);
3190f7d52f4SChris Mason 		if (ret) {
3200f7d52f4SChris Mason printk("failed2\n");
3210f7d52f4SChris Mason 			kfree(root);
3220f7d52f4SChris Mason 			return ERR_PTR(ret);
3230f7d52f4SChris Mason 		}
3240f7d52f4SChris Mason 		goto insert;
3250f7d52f4SChris Mason 	}
3260f7d52f4SChris Mason 
3270f7d52f4SChris Mason 	__setup_root(fs_info->sb->s_blocksize, root, fs_info,
3280f7d52f4SChris Mason 		     location->objectid);
3290f7d52f4SChris Mason 
3300f7d52f4SChris Mason 	path = btrfs_alloc_path();
3310f7d52f4SChris Mason 	BUG_ON(!path);
3320f7d52f4SChris Mason 	ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
3330f7d52f4SChris Mason 	if (ret != 0) {
3340f7d52f4SChris Mason printk("internal search_slot gives us %d\n", ret);
3350f7d52f4SChris Mason 		if (ret > 0)
3360f7d52f4SChris Mason 			ret = -ENOENT;
3370f7d52f4SChris Mason 		goto out;
3380f7d52f4SChris Mason 	}
3390f7d52f4SChris Mason 	l = btrfs_buffer_leaf(path->nodes[0]);
3400f7d52f4SChris Mason 	memcpy(&root->root_item,
3410f7d52f4SChris Mason 	       btrfs_item_ptr(l, path->slots[0], struct btrfs_root_item),
3420f7d52f4SChris Mason 	       sizeof(root->root_item));
3430f7d52f4SChris Mason 	memcpy(&root->root_key, location, sizeof(*location));
3440f7d52f4SChris Mason 	ret = 0;
3450f7d52f4SChris Mason out:
3460f7d52f4SChris Mason 	btrfs_release_path(root, path);
3470f7d52f4SChris Mason 	btrfs_free_path(path);
3480f7d52f4SChris Mason 	if (ret) {
3490f7d52f4SChris Mason 		kfree(root);
3500f7d52f4SChris Mason 		return ERR_PTR(ret);
3510f7d52f4SChris Mason 	}
3520f7d52f4SChris Mason 	root->node = read_tree_block(root,
3530f7d52f4SChris Mason 				     btrfs_root_blocknr(&root->root_item));
3540f7d52f4SChris Mason 	BUG_ON(!root->node);
3550f7d52f4SChris Mason insert:
3560f7d52f4SChris Mason printk("inserting %p\n", root);
3570f7d52f4SChris Mason 	root->ref_cows = 1;
3582619ba1fSChris Mason 	ret = radix_tree_insert(&fs_info->fs_roots_radix,
3592619ba1fSChris Mason 				(unsigned long)root->root_key.objectid,
3600f7d52f4SChris Mason 				root);
3610f7d52f4SChris Mason 	if (ret) {
3620f7d52f4SChris Mason printk("radix_tree_insert gives us %d\n", ret);
3630f7d52f4SChris Mason 		brelse(root->node);
3640f7d52f4SChris Mason 		kfree(root);
3650f7d52f4SChris Mason 		return ERR_PTR(ret);
3660f7d52f4SChris Mason 	}
3671b05da2eSChris Mason 	ret = btrfs_find_highest_inode(root, &highest_inode);
3681b05da2eSChris Mason 	if (ret == 0) {
3691b05da2eSChris Mason 		root->highest_inode = highest_inode;
3701b05da2eSChris Mason 		root->last_inode_alloc = highest_inode;
3711b05da2eSChris Mason printk("highest inode is %Lu\n", highest_inode);
3721b05da2eSChris Mason 	}
3730f7d52f4SChris Mason printk("all worked\n");
3740f7d52f4SChris Mason 	return root;
3750f7d52f4SChris Mason }
3760f7d52f4SChris Mason 
3772c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb)
378eb60ceacSChris Mason {
379e20d96d6SChris Mason 	struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root),
380e20d96d6SChris Mason 						 GFP_NOFS);
381e20d96d6SChris Mason 	struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root),
382e20d96d6SChris Mason 					       GFP_NOFS);
383e20d96d6SChris Mason 	struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info),
384e20d96d6SChris Mason 						GFP_NOFS);
385eb60ceacSChris Mason 	int ret;
3862c90e5d6SChris Mason 	struct btrfs_super_block *disk_super;
387eb60ceacSChris Mason 
3888ef97622SChris Mason 	init_bit_radix(&fs_info->pinned_radix);
3898ef97622SChris Mason 	init_bit_radix(&fs_info->pending_del_radix);
3900f7d52f4SChris Mason 	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS);
3912c90e5d6SChris Mason 	sb_set_blocksize(sb, 4096);
3929f5fae2fSChris Mason 	fs_info->running_transaction = NULL;
3939f5fae2fSChris Mason 	fs_info->tree_root = tree_root;
3949f5fae2fSChris Mason 	fs_info->extent_root = extent_root;
395e20d96d6SChris Mason 	fs_info->sb = sb;
396d98237b3SChris Mason 	fs_info->btree_inode = new_inode(sb);
397d98237b3SChris Mason 	fs_info->btree_inode->i_ino = 1;
3982c90e5d6SChris Mason 	fs_info->btree_inode->i_nlink = 1;
399d98237b3SChris Mason 	fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size;
400d98237b3SChris Mason 	fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
4010f7d52f4SChris Mason 	BTRFS_I(fs_info->btree_inode)->root = tree_root;
4020f7d52f4SChris Mason 	memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
4030f7d52f4SChris Mason 	       sizeof(struct btrfs_key));
40422b0ebdaSChris Mason 	insert_inode_hash(fs_info->btree_inode);
405d98237b3SChris Mason 	mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
40687cbda5cSChris Mason 	fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
40730ae8467SChris Mason 	spin_lock_init(&fs_info->hash_lock);
40830ae8467SChris Mason 	if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) {
40987cbda5cSChris Mason 		printk("failed to allocate sha256 hash\n");
41087cbda5cSChris Mason 		return NULL;
41187cbda5cSChris Mason 	}
41279154b1bSChris Mason 	mutex_init(&fs_info->trans_mutex);
413d561c025SChris Mason 	mutex_init(&fs_info->fs_mutex);
4149f5fae2fSChris Mason 	memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
4159f5fae2fSChris Mason 	memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
4163768f368SChris Mason 
4172c90e5d6SChris Mason 	__setup_root(sb->s_blocksize, tree_root,
4182c90e5d6SChris Mason 		     fs_info, BTRFS_ROOT_TREE_OBJECTID);
4192c90e5d6SChris Mason 	fs_info->sb_buffer = read_tree_block(tree_root,
4202c90e5d6SChris Mason 					     BTRFS_SUPER_INFO_OFFSET /
4212c90e5d6SChris Mason 					     sb->s_blocksize);
422d98237b3SChris Mason 
4230f7d52f4SChris Mason 	if (!fs_info->sb_buffer)
424d98237b3SChris Mason 		return NULL;
425d98237b3SChris Mason 	disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data;
4260f7d52f4SChris Mason 	if (!btrfs_super_root(disk_super))
4272c90e5d6SChris Mason 		return NULL;
4280f7d52f4SChris Mason 
429d98237b3SChris Mason 	fs_info->disk_super = disk_super;
430e20d96d6SChris Mason 	tree_root->node = read_tree_block(tree_root,
431e20d96d6SChris Mason 					  btrfs_super_root(disk_super));
4323768f368SChris Mason 	BUG_ON(!tree_root->node);
4333768f368SChris Mason 
4342c90e5d6SChris Mason 	mutex_lock(&fs_info->fs_mutex);
4352c90e5d6SChris Mason 	ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info,
436e20d96d6SChris Mason 				  BTRFS_EXTENT_TREE_OBJECTID, extent_root);
4373768f368SChris Mason 	BUG_ON(ret);
4383768f368SChris Mason 
4390f7d52f4SChris Mason 	fs_info->generation = btrfs_super_generation(disk_super) + 1;
440d6e4a428SChris Mason 	memset(&fs_info->kobj, 0, sizeof(fs_info->kobj));
441d6e4a428SChris Mason 	kobj_set_kset_s(fs_info, btrfs_subsys);
442d6e4a428SChris Mason 	kobject_set_name(&fs_info->kobj, "%s", sb->s_id);
443d6e4a428SChris Mason 	kobject_register(&fs_info->kobj);
4445be6f7f1SChris Mason 	mutex_unlock(&fs_info->fs_mutex);
4450f7d52f4SChris Mason 	return tree_root;
446eb60ceacSChris Mason }
447eb60ceacSChris Mason 
448e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
44979154b1bSChris Mason 		      *root)
450cfaa7295SChris Mason {
451d5719762SChris Mason 	struct buffer_head *bh = root->fs_info->sb_buffer;
4522c90e5d6SChris Mason 
453d5719762SChris Mason 	btrfs_set_super_root(root->fs_info->disk_super,
454d5719762SChris Mason 			     root->fs_info->tree_root->node->b_blocknr);
455d5719762SChris Mason 	lock_buffer(bh);
4562c90e5d6SChris Mason 	WARN_ON(atomic_read(&bh->b_count) < 1);
457d5719762SChris Mason 	clear_buffer_dirty(bh);
45887cbda5cSChris Mason 	csum_tree_block(root, bh, 0);
459d5719762SChris Mason 	bh->b_end_io = end_buffer_write_sync;
460d5719762SChris Mason 	get_bh(bh);
461d5719762SChris Mason 	submit_bh(WRITE, bh);
462d5719762SChris Mason 	wait_on_buffer(bh);
463d5719762SChris Mason 	if (!buffer_uptodate(bh)) {
464d5719762SChris Mason 		WARN_ON(1);
465d5719762SChris Mason 		return -EIO;
466cfaa7295SChris Mason 	}
467cfaa7295SChris Mason 	return 0;
468cfaa7295SChris Mason }
469cfaa7295SChris Mason 
4702619ba1fSChris Mason static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
4712619ba1fSChris Mason {
4722619ba1fSChris Mason 	radix_tree_delete(&fs_info->fs_roots_radix,
4732619ba1fSChris Mason 			  (unsigned long)root->root_key.objectid);
4742619ba1fSChris Mason 	if (root->inode)
4752619ba1fSChris Mason 		iput(root->inode);
4762619ba1fSChris Mason 	if (root->node)
4772619ba1fSChris Mason 		brelse(root->node);
4782619ba1fSChris Mason 	if (root->commit_root)
4792619ba1fSChris Mason 		brelse(root->commit_root);
4802619ba1fSChris Mason 	kfree(root);
4812619ba1fSChris Mason 	return 0;
4822619ba1fSChris Mason }
4832619ba1fSChris Mason 
4840f7d52f4SChris Mason int del_fs_roots(struct btrfs_fs_info *fs_info)
4850f7d52f4SChris Mason {
4860f7d52f4SChris Mason 	int ret;
4870f7d52f4SChris Mason 	struct btrfs_root *gang[8];
4880f7d52f4SChris Mason 	int i;
4890f7d52f4SChris Mason 
4900f7d52f4SChris Mason 	while(1) {
4910f7d52f4SChris Mason 		ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
4920f7d52f4SChris Mason 					     (void **)gang, 0,
4930f7d52f4SChris Mason 					     ARRAY_SIZE(gang));
4940f7d52f4SChris Mason 		if (!ret)
4950f7d52f4SChris Mason 			break;
4962619ba1fSChris Mason 		for (i = 0; i < ret; i++)
4972619ba1fSChris Mason 			free_fs_root(fs_info, gang[i]);
4980f7d52f4SChris Mason 	}
4990f7d52f4SChris Mason 	return 0;
5000f7d52f4SChris Mason }
5010f7d52f4SChris Mason 
502e20d96d6SChris Mason int close_ctree(struct btrfs_root *root)
503eb60ceacSChris Mason {
5043768f368SChris Mason 	int ret;
505e089f05cSChris Mason 	struct btrfs_trans_handle *trans;
5060f7d52f4SChris Mason 	struct btrfs_fs_info *fs_info = root->fs_info;
507e089f05cSChris Mason 
5080f7d52f4SChris Mason 	mutex_lock(&fs_info->fs_mutex);
50979154b1bSChris Mason 	trans = btrfs_start_transaction(root, 1);
51079154b1bSChris Mason 	btrfs_commit_transaction(trans, root);
51179154b1bSChris Mason 	/* run commit again to  drop the original snapshot */
51279154b1bSChris Mason 	trans = btrfs_start_transaction(root, 1);
51379154b1bSChris Mason 	btrfs_commit_transaction(trans, root);
51479154b1bSChris Mason 	ret = btrfs_write_and_wait_transaction(NULL, root);
5159f5fae2fSChris Mason 	BUG_ON(ret);
51679154b1bSChris Mason 	write_ctree_super(NULL, root);
5170f7d52f4SChris Mason 	mutex_unlock(&fs_info->fs_mutex);
518ed2ff2cbSChris Mason 
5190f7d52f4SChris Mason 	if (fs_info->extent_root->node)
5200f7d52f4SChris Mason 		btrfs_block_release(fs_info->extent_root,
5210f7d52f4SChris Mason 				    fs_info->extent_root->node);
5220f7d52f4SChris Mason 	if (fs_info->tree_root->node)
5230f7d52f4SChris Mason 		btrfs_block_release(fs_info->tree_root,
5240f7d52f4SChris Mason 				    fs_info->tree_root->node);
5250f7d52f4SChris Mason 	btrfs_block_release(root, fs_info->sb_buffer);
5260f7d52f4SChris Mason 	crypto_free_hash(fs_info->hash_tfm);
5270f7d52f4SChris Mason 	truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
5280f7d52f4SChris Mason 	iput(fs_info->btree_inode);
5290f7d52f4SChris Mason 	del_fs_roots(fs_info);
5300f7d52f4SChris Mason 	kfree(fs_info->extent_root);
5310f7d52f4SChris Mason 	kfree(fs_info->tree_root);
5320f7d52f4SChris Mason 	kobject_unregister(&fs_info->kobj);
533eb60ceacSChris Mason 	return 0;
534eb60ceacSChris Mason }
535eb60ceacSChris Mason 
536e20d96d6SChris Mason void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf)
537eb60ceacSChris Mason {
5387cfcc17eSChris Mason 	brelse(buf);
539eb60ceacSChris Mason }
540eb60ceacSChris Mason 
541