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 137eccb903SChris Mason struct dev_lookup { 147eccb903SChris Mason u64 block_start; 157eccb903SChris Mason u64 num_blocks; 16b4100d64SChris Mason u64 device_id; 177eccb903SChris Mason struct block_device *bdev; 187eccb903SChris Mason }; 197eccb903SChris Mason 208352d8a4SChris Mason int btrfs_insert_dev_radix(struct btrfs_root *root, 218352d8a4SChris Mason struct block_device *bdev, 22b4100d64SChris Mason u64 device_id, 238352d8a4SChris Mason u64 block_start, 248352d8a4SChris Mason u64 num_blocks) 258352d8a4SChris Mason { 268352d8a4SChris Mason struct dev_lookup *lookup; 278352d8a4SChris Mason int ret; 288352d8a4SChris Mason 298352d8a4SChris Mason lookup = kmalloc(sizeof(*lookup), GFP_NOFS); 308352d8a4SChris Mason if (!lookup) 318352d8a4SChris Mason return -ENOMEM; 328352d8a4SChris Mason lookup->block_start = block_start; 338352d8a4SChris Mason lookup->num_blocks = num_blocks; 348352d8a4SChris Mason lookup->bdev = bdev; 35b4100d64SChris Mason lookup->device_id = device_id; 368352d8a4SChris Mason 378352d8a4SChris Mason ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + 388352d8a4SChris Mason num_blocks - 1, lookup); 398352d8a4SChris Mason return ret; 408352d8a4SChris Mason } 418352d8a4SChris Mason 427eccb903SChris Mason u64 bh_blocknr(struct buffer_head *bh) 437eccb903SChris Mason { 447eccb903SChris Mason int blkbits = bh->b_page->mapping->host->i_blkbits; 457eccb903SChris Mason u64 blocknr = bh->b_page->index << (PAGE_CACHE_SHIFT - blkbits); 467eccb903SChris Mason unsigned long offset; 477eccb903SChris Mason 487eccb903SChris Mason if (PageHighMem(bh->b_page)) 497eccb903SChris Mason offset = (unsigned long)bh->b_data; 507eccb903SChris Mason else 517eccb903SChris Mason offset = bh->b_data - (char *)page_address(bh->b_page); 527eccb903SChris Mason blocknr += offset >> (PAGE_CACHE_SHIFT - blkbits); 537eccb903SChris Mason return blocknr; 547eccb903SChris Mason } 557eccb903SChris Mason 56e20d96d6SChris Mason static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) 57eb60ceacSChris Mason { 58e20d96d6SChris Mason struct btrfs_node *node = btrfs_buffer_node(buf); 597eccb903SChris Mason if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { 608352d8a4SChris Mason printk(KERN_CRIT "bh_blocknr(buf) is %Lu, header is %Lu\n", 618352d8a4SChris Mason bh_blocknr(buf), btrfs_header_blocknr(&node->header)); 629a8dd150SChris Mason BUG(); 63d98237b3SChris Mason } 649a8dd150SChris Mason return 0; 65eb60ceacSChris Mason } 66eb60ceacSChris Mason 67d98237b3SChris Mason struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) 68ed2ff2cbSChris Mason { 69d98237b3SChris Mason struct address_space *mapping = root->fs_info->btree_inode->i_mapping; 70d98237b3SChris Mason int blockbits = root->fs_info->sb->s_blocksize_bits; 71d98237b3SChris Mason unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); 72d98237b3SChris Mason struct page *page; 73d98237b3SChris Mason struct buffer_head *bh; 74d98237b3SChris Mason struct buffer_head *head; 75d98237b3SChris Mason struct buffer_head *ret = NULL; 76d98237b3SChris Mason 772c90e5d6SChris Mason 78d98237b3SChris Mason page = find_lock_page(mapping, index); 79d98237b3SChris Mason if (!page) 80d98237b3SChris Mason return NULL; 81d98237b3SChris Mason 82d98237b3SChris Mason if (!page_has_buffers(page)) 83d98237b3SChris Mason goto out_unlock; 84d98237b3SChris Mason 85d98237b3SChris Mason head = page_buffers(page); 86d98237b3SChris Mason bh = head; 87d98237b3SChris Mason do { 887eccb903SChris Mason if (buffer_mapped(bh) && bh_blocknr(bh) == blocknr) { 89d98237b3SChris Mason ret = bh; 90d98237b3SChris Mason get_bh(bh); 91d98237b3SChris Mason goto out_unlock; 92d98237b3SChris Mason } 93d98237b3SChris Mason bh = bh->b_this_page; 94d98237b3SChris Mason } while (bh != head); 95d98237b3SChris Mason out_unlock: 96d98237b3SChris Mason unlock_page(page); 97d6025579SChris Mason if (ret) { 9822b0ebdaSChris Mason touch_buffer(ret); 99d6025579SChris Mason } 100d98237b3SChris Mason page_cache_release(page); 101d98237b3SChris Mason return ret; 102ed2ff2cbSChris Mason } 103ed2ff2cbSChris Mason 1048352d8a4SChris Mason int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, 1057eccb903SChris Mason u64 logical) 1067eccb903SChris Mason { 1077eccb903SChris Mason struct dev_lookup *lookup[2]; 1087eccb903SChris Mason 1097eccb903SChris Mason int ret; 1107eccb903SChris Mason 111236454dfSChris Mason if (logical == 0) { 112236454dfSChris Mason bh->b_bdev = NULL; 113236454dfSChris Mason bh->b_blocknr = 0; 114236454dfSChris Mason set_buffer_mapped(bh); 115236454dfSChris Mason return 0; 116236454dfSChris Mason } 1177eccb903SChris Mason root = root->fs_info->dev_root; 1187eccb903SChris Mason ret = radix_tree_gang_lookup(&root->fs_info->dev_radix, 1197eccb903SChris Mason (void **)lookup, 1207eccb903SChris Mason (unsigned long)logical, 1217eccb903SChris Mason ARRAY_SIZE(lookup)); 1227eccb903SChris Mason if (ret == 0 || lookup[0]->block_start > logical || 1237eccb903SChris Mason lookup[0]->block_start + lookup[0]->num_blocks <= logical) { 1247eccb903SChris Mason ret = -ENOENT; 1257eccb903SChris Mason goto out; 1267eccb903SChris Mason } 1277eccb903SChris Mason bh->b_bdev = lookup[0]->bdev; 1287eccb903SChris Mason bh->b_blocknr = logical - lookup[0]->block_start; 1297eccb903SChris Mason set_buffer_mapped(bh); 1307eccb903SChris Mason ret = 0; 1317eccb903SChris Mason out: 1327eccb903SChris Mason return ret; 1337eccb903SChris Mason } 1347eccb903SChris Mason 135d98237b3SChris Mason struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, 136d98237b3SChris Mason u64 blocknr) 137eb60ceacSChris Mason { 138d98237b3SChris Mason struct address_space *mapping = root->fs_info->btree_inode->i_mapping; 139d98237b3SChris Mason int blockbits = root->fs_info->sb->s_blocksize_bits; 140d98237b3SChris Mason unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); 141d98237b3SChris Mason struct page *page; 142d98237b3SChris Mason struct buffer_head *bh; 143d98237b3SChris Mason struct buffer_head *head; 144d98237b3SChris Mason struct buffer_head *ret = NULL; 1457eccb903SChris Mason int err; 146d98237b3SChris Mason u64 first_block = index << (PAGE_CACHE_SHIFT - blockbits); 14722b0ebdaSChris Mason 148d98237b3SChris Mason page = grab_cache_page(mapping, index); 149d98237b3SChris Mason if (!page) 150d98237b3SChris Mason return NULL; 151d98237b3SChris Mason 152d98237b3SChris Mason if (!page_has_buffers(page)) 153d98237b3SChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 0); 154d98237b3SChris Mason head = page_buffers(page); 155d98237b3SChris Mason bh = head; 156d98237b3SChris Mason do { 157d98237b3SChris Mason if (!buffer_mapped(bh)) { 1588352d8a4SChris Mason err = btrfs_map_bh_to_logical(root, bh, first_block); 1597eccb903SChris Mason BUG_ON(err); 160e20d96d6SChris Mason } 1617eccb903SChris Mason if (bh_blocknr(bh) == blocknr) { 162d98237b3SChris Mason ret = bh; 163d98237b3SChris Mason get_bh(bh); 164d98237b3SChris Mason goto out_unlock; 165d98237b3SChris Mason } 166d98237b3SChris Mason bh = bh->b_this_page; 167d98237b3SChris Mason first_block++; 168d98237b3SChris Mason } while (bh != head); 169d98237b3SChris Mason out_unlock: 170d98237b3SChris Mason unlock_page(page); 17122b0ebdaSChris Mason if (ret) 17222b0ebdaSChris Mason touch_buffer(ret); 173d98237b3SChris Mason page_cache_release(page); 174d98237b3SChris Mason return ret; 175d98237b3SChris Mason } 176d98237b3SChris Mason 177d98237b3SChris Mason static int btree_get_block(struct inode *inode, sector_t iblock, 178d98237b3SChris Mason struct buffer_head *bh, int create) 179d98237b3SChris Mason { 1807eccb903SChris Mason int err; 1817eccb903SChris Mason struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; 1828352d8a4SChris Mason err = btrfs_map_bh_to_logical(root, bh, iblock); 1837eccb903SChris Mason return err; 184d98237b3SChris Mason } 185d98237b3SChris Mason 186f254e52cSChris Mason int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, 187f254e52cSChris Mason char *result) 18887cbda5cSChris Mason { 18987cbda5cSChris Mason struct scatterlist sg; 19087cbda5cSChris Mason struct crypto_hash *tfm = root->fs_info->hash_tfm; 19187cbda5cSChris Mason struct hash_desc desc; 19287cbda5cSChris Mason int ret; 19387cbda5cSChris Mason 19487cbda5cSChris Mason desc.tfm = tfm; 19587cbda5cSChris Mason desc.flags = 0; 196f254e52cSChris Mason sg_init_one(&sg, data, len); 19787cbda5cSChris Mason spin_lock(&root->fs_info->hash_lock); 19822b0ebdaSChris Mason ret = crypto_hash_digest(&desc, &sg, 1, result); 19987cbda5cSChris Mason spin_unlock(&root->fs_info->hash_lock); 20087cbda5cSChris Mason if (ret) { 20187cbda5cSChris Mason printk("sha256 digest failed\n"); 20287cbda5cSChris Mason } 203f254e52cSChris Mason return ret; 204f254e52cSChris Mason } 205f254e52cSChris Mason static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, 206f254e52cSChris Mason int verify) 207f254e52cSChris Mason { 208f254e52cSChris Mason char result[BTRFS_CSUM_SIZE]; 209f254e52cSChris Mason int ret; 210f254e52cSChris Mason struct btrfs_node *node; 211f254e52cSChris Mason 212f254e52cSChris Mason ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE, 213f254e52cSChris Mason bh->b_size - BTRFS_CSUM_SIZE, result); 214f254e52cSChris Mason if (ret) 215f254e52cSChris Mason return ret; 21687cbda5cSChris Mason if (verify) { 217f254e52cSChris Mason if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) { 2187eccb903SChris Mason printk("checksum verify failed on %Lu\n", 2197eccb903SChris Mason bh_blocknr(bh)); 220f254e52cSChris Mason return 1; 221f254e52cSChris Mason } 222f254e52cSChris Mason } else { 223f254e52cSChris Mason node = btrfs_buffer_node(bh); 22422b0ebdaSChris Mason memcpy(node->header.csum, result, BTRFS_CSUM_SIZE); 225f254e52cSChris Mason } 22687cbda5cSChris Mason return 0; 22787cbda5cSChris Mason } 22887cbda5cSChris Mason 229d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 230d98237b3SChris Mason { 23187cbda5cSChris Mason struct buffer_head *bh; 2320f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 23387cbda5cSChris Mason struct buffer_head *head; 23487cbda5cSChris Mason if (!page_has_buffers(page)) { 23587cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 23687cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 23787cbda5cSChris Mason } 23887cbda5cSChris Mason head = page_buffers(page); 23987cbda5cSChris Mason bh = head; 24087cbda5cSChris Mason do { 24187cbda5cSChris Mason if (buffer_dirty(bh)) 24287cbda5cSChris Mason csum_tree_block(root, bh, 0); 24387cbda5cSChris Mason bh = bh->b_this_page; 24487cbda5cSChris Mason } while (bh != head); 245d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 246d98237b3SChris Mason } 247d98237b3SChris Mason 248d98237b3SChris Mason static int btree_readpage(struct file * file, struct page * page) 249d98237b3SChris Mason { 250d98237b3SChris Mason return block_read_full_page(page, btree_get_block); 251d98237b3SChris Mason } 252d98237b3SChris Mason 253d98237b3SChris Mason static struct address_space_operations btree_aops = { 254d98237b3SChris Mason .readpage = btree_readpage, 255d98237b3SChris Mason .writepage = btree_writepage, 256d98237b3SChris Mason .sync_page = block_sync_page, 257d98237b3SChris Mason }; 258123abc88SChris Mason 259e20d96d6SChris Mason struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) 260e20d96d6SChris Mason { 261d98237b3SChris Mason struct buffer_head *bh = NULL; 262e20d96d6SChris Mason 263d98237b3SChris Mason bh = btrfs_find_create_tree_block(root, blocknr); 264d98237b3SChris Mason if (!bh) 265d98237b3SChris Mason return bh; 2669d64272cSChris Mason if (buffer_uptodate(bh)) 2679d64272cSChris Mason goto uptodate; 268d98237b3SChris Mason lock_buffer(bh); 269d98237b3SChris Mason if (!buffer_uptodate(bh)) { 270d98237b3SChris Mason get_bh(bh); 271d98237b3SChris Mason bh->b_end_io = end_buffer_read_sync; 272d98237b3SChris Mason submit_bh(READ, bh); 273d98237b3SChris Mason wait_on_buffer(bh); 274d98237b3SChris Mason if (!buffer_uptodate(bh)) 275d98237b3SChris Mason goto fail; 27687cbda5cSChris Mason csum_tree_block(root, bh, 1); 277d98237b3SChris Mason } else { 278d98237b3SChris Mason unlock_buffer(bh); 279d98237b3SChris Mason } 2809d64272cSChris Mason uptodate: 281d98237b3SChris Mason if (check_tree_block(root, bh)) 282cfaa7295SChris Mason BUG(); 283d98237b3SChris Mason return bh; 284d98237b3SChris Mason fail: 285d98237b3SChris Mason brelse(bh); 286d98237b3SChris Mason return NULL; 287eb60ceacSChris Mason } 288eb60ceacSChris Mason 289e089f05cSChris Mason int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 290e20d96d6SChris Mason struct buffer_head *buf) 291ed2ff2cbSChris Mason { 292d6025579SChris Mason WARN_ON(atomic_read(&buf->b_count) == 0); 293e20d96d6SChris Mason mark_buffer_dirty(buf); 294ed2ff2cbSChris Mason return 0; 295ed2ff2cbSChris Mason } 296ed2ff2cbSChris Mason 297e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 298e20d96d6SChris Mason struct buffer_head *buf) 299ed2ff2cbSChris Mason { 300d6025579SChris Mason WARN_ON(atomic_read(&buf->b_count) == 0); 301e20d96d6SChris Mason clear_buffer_dirty(buf); 302ed2ff2cbSChris Mason return 0; 303ed2ff2cbSChris Mason } 304ed2ff2cbSChris Mason 3052c90e5d6SChris Mason static int __setup_root(int blocksize, 3069f5fae2fSChris Mason struct btrfs_root *root, 3079f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 308e20d96d6SChris Mason u64 objectid) 309d97e63b6SChris Mason { 310cfaa7295SChris Mason root->node = NULL; 3110f7d52f4SChris Mason root->inode = NULL; 312a28ec197SChris Mason root->commit_root = NULL; 3132c90e5d6SChris Mason root->blocksize = blocksize; 314123abc88SChris Mason root->ref_cows = 0; 3159f5fae2fSChris Mason root->fs_info = fs_info; 3160f7d52f4SChris Mason root->objectid = objectid; 3170f7d52f4SChris Mason root->last_trans = 0; 3181b05da2eSChris Mason root->highest_inode = 0; 3191b05da2eSChris Mason root->last_inode_alloc = 0; 3203768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 3213768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 3224d775673SChris Mason root->root_key.objectid = objectid; 3233768f368SChris Mason return 0; 3243768f368SChris Mason } 3253768f368SChris Mason 3262c90e5d6SChris Mason static int find_and_setup_root(int blocksize, 3279f5fae2fSChris Mason struct btrfs_root *tree_root, 3289f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 3299f5fae2fSChris Mason u64 objectid, 330e20d96d6SChris Mason struct btrfs_root *root) 3313768f368SChris Mason { 3323768f368SChris Mason int ret; 3333768f368SChris Mason 3342c90e5d6SChris Mason __setup_root(blocksize, root, fs_info, objectid); 3353768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 3363768f368SChris Mason &root->root_item, &root->root_key); 3373768f368SChris Mason BUG_ON(ret); 3383768f368SChris Mason 3393768f368SChris Mason root->node = read_tree_block(root, 3403768f368SChris Mason btrfs_root_blocknr(&root->root_item)); 3413768f368SChris Mason BUG_ON(!root->node); 342d97e63b6SChris Mason return 0; 343d97e63b6SChris Mason } 344d97e63b6SChris Mason 3450f7d52f4SChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 3460f7d52f4SChris Mason struct btrfs_key *location) 3470f7d52f4SChris Mason { 3480f7d52f4SChris Mason struct btrfs_root *root; 3490f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 3500f7d52f4SChris Mason struct btrfs_path *path; 3510f7d52f4SChris Mason struct btrfs_leaf *l; 3521b05da2eSChris Mason u64 highest_inode; 3530f7d52f4SChris Mason int ret = 0; 3540f7d52f4SChris Mason 3550f7d52f4SChris Mason printk("read_fs_root looking for %Lu %Lu %u\n", location->objectid, location->offset, location->flags); 3562619ba1fSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 3572619ba1fSChris Mason (unsigned long)location->objectid); 3582619ba1fSChris Mason if (root) { 3592619ba1fSChris Mason printk("found %p in cache\n", root); 3602619ba1fSChris Mason return root; 3612619ba1fSChris Mason } 3620f7d52f4SChris Mason root = kmalloc(sizeof(*root), GFP_NOFS); 3630f7d52f4SChris Mason if (!root) { 3640f7d52f4SChris Mason printk("failed1\n"); 3650f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 3660f7d52f4SChris Mason } 3670f7d52f4SChris Mason if (location->offset == (u64)-1) { 3680f7d52f4SChris Mason ret = find_and_setup_root(fs_info->sb->s_blocksize, 3690f7d52f4SChris Mason fs_info->tree_root, fs_info, 3700f7d52f4SChris Mason location->objectid, root); 3710f7d52f4SChris Mason if (ret) { 3720f7d52f4SChris Mason printk("failed2\n"); 3730f7d52f4SChris Mason kfree(root); 3740f7d52f4SChris Mason return ERR_PTR(ret); 3750f7d52f4SChris Mason } 3760f7d52f4SChris Mason goto insert; 3770f7d52f4SChris Mason } 3780f7d52f4SChris Mason 3790f7d52f4SChris Mason __setup_root(fs_info->sb->s_blocksize, root, fs_info, 3800f7d52f4SChris Mason location->objectid); 3810f7d52f4SChris Mason 3820f7d52f4SChris Mason path = btrfs_alloc_path(); 3830f7d52f4SChris Mason BUG_ON(!path); 3840f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 3850f7d52f4SChris Mason if (ret != 0) { 3860f7d52f4SChris Mason printk("internal search_slot gives us %d\n", ret); 3870f7d52f4SChris Mason if (ret > 0) 3880f7d52f4SChris Mason ret = -ENOENT; 3890f7d52f4SChris Mason goto out; 3900f7d52f4SChris Mason } 3910f7d52f4SChris Mason l = btrfs_buffer_leaf(path->nodes[0]); 3920f7d52f4SChris Mason memcpy(&root->root_item, 3930f7d52f4SChris Mason btrfs_item_ptr(l, path->slots[0], struct btrfs_root_item), 3940f7d52f4SChris Mason sizeof(root->root_item)); 3950f7d52f4SChris Mason memcpy(&root->root_key, location, sizeof(*location)); 3960f7d52f4SChris Mason ret = 0; 3970f7d52f4SChris Mason out: 3980f7d52f4SChris Mason btrfs_release_path(root, path); 3990f7d52f4SChris Mason btrfs_free_path(path); 4000f7d52f4SChris Mason if (ret) { 4010f7d52f4SChris Mason kfree(root); 4020f7d52f4SChris Mason return ERR_PTR(ret); 4030f7d52f4SChris Mason } 4040f7d52f4SChris Mason root->node = read_tree_block(root, 4050f7d52f4SChris Mason btrfs_root_blocknr(&root->root_item)); 4060f7d52f4SChris Mason BUG_ON(!root->node); 4070f7d52f4SChris Mason insert: 4080f7d52f4SChris Mason printk("inserting %p\n", root); 4090f7d52f4SChris Mason root->ref_cows = 1; 4102619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 4112619ba1fSChris Mason (unsigned long)root->root_key.objectid, 4120f7d52f4SChris Mason root); 4130f7d52f4SChris Mason if (ret) { 4140f7d52f4SChris Mason printk("radix_tree_insert gives us %d\n", ret); 4150f7d52f4SChris Mason brelse(root->node); 4160f7d52f4SChris Mason kfree(root); 4170f7d52f4SChris Mason return ERR_PTR(ret); 4180f7d52f4SChris Mason } 4191b05da2eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 4201b05da2eSChris Mason if (ret == 0) { 4211b05da2eSChris Mason root->highest_inode = highest_inode; 4221b05da2eSChris Mason root->last_inode_alloc = highest_inode; 4231b05da2eSChris Mason printk("highest inode is %Lu\n", highest_inode); 4241b05da2eSChris Mason } 4250f7d52f4SChris Mason printk("all worked\n"); 4260f7d52f4SChris Mason return root; 4270f7d52f4SChris Mason } 4280f7d52f4SChris Mason 429b4100d64SChris Mason static int btrfs_open_disk(struct btrfs_root *root, u64 device_id, 430b4100d64SChris Mason u64 block_start, u64 num_blocks, 4318352d8a4SChris Mason char *filename, int name_len) 4328352d8a4SChris Mason { 4338352d8a4SChris Mason char *null_filename; 4348352d8a4SChris Mason struct block_device *bdev; 4358352d8a4SChris Mason int ret; 4368352d8a4SChris Mason 4378352d8a4SChris Mason null_filename = kmalloc(name_len + 1, GFP_NOFS); 4388352d8a4SChris Mason if (!null_filename) 4398352d8a4SChris Mason return -ENOMEM; 4408352d8a4SChris Mason memcpy(null_filename, filename, name_len); 4418352d8a4SChris Mason null_filename[name_len] = '\0'; 4428352d8a4SChris Mason 4438352d8a4SChris Mason bdev = open_bdev_excl(null_filename, O_RDWR, root->fs_info->sb); 4448352d8a4SChris Mason if (IS_ERR(bdev)) { 4458352d8a4SChris Mason ret = PTR_ERR(bdev); 4468352d8a4SChris Mason goto out; 4478352d8a4SChris Mason } 4488352d8a4SChris Mason set_blocksize(bdev, root->fs_info->sb->s_blocksize); 449b4100d64SChris Mason ret = btrfs_insert_dev_radix(root, bdev, device_id, 450b4100d64SChris Mason block_start, num_blocks); 4518352d8a4SChris Mason BUG_ON(ret); 4528352d8a4SChris Mason ret = 0; 4538352d8a4SChris Mason out: 4548352d8a4SChris Mason kfree(null_filename); 4558352d8a4SChris Mason return ret; 4568352d8a4SChris Mason } 4578352d8a4SChris Mason 4588352d8a4SChris Mason static int read_device_info(struct btrfs_root *root) 4598352d8a4SChris Mason { 4608352d8a4SChris Mason struct btrfs_path *path; 4618352d8a4SChris Mason int ret; 4628352d8a4SChris Mason struct btrfs_key key; 4638352d8a4SChris Mason struct btrfs_leaf *leaf; 4648352d8a4SChris Mason struct btrfs_device_item *dev_item; 4658352d8a4SChris Mason int nritems; 4668352d8a4SChris Mason int slot; 4678352d8a4SChris Mason 4688352d8a4SChris Mason root = root->fs_info->dev_root; 4698352d8a4SChris Mason 4708352d8a4SChris Mason path = btrfs_alloc_path(); 4718352d8a4SChris Mason if (!path) 4728352d8a4SChris Mason return -ENOMEM; 4738352d8a4SChris Mason key.objectid = 0; 4748352d8a4SChris Mason key.offset = 0; 4758352d8a4SChris Mason key.flags = 0; 4768352d8a4SChris Mason btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); 4778352d8a4SChris Mason 4788352d8a4SChris Mason mutex_lock(&root->fs_info->fs_mutex); 4798352d8a4SChris Mason ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 4808352d8a4SChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 4818352d8a4SChris Mason nritems = btrfs_header_nritems(&leaf->header); 4828352d8a4SChris Mason while(1) { 4838352d8a4SChris Mason slot = path->slots[0]; 4848352d8a4SChris Mason if (slot >= nritems) { 4858352d8a4SChris Mason ret = btrfs_next_leaf(root, path); 4868352d8a4SChris Mason if (ret) 4878352d8a4SChris Mason break; 4888352d8a4SChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 4898352d8a4SChris Mason nritems = btrfs_header_nritems(&leaf->header); 4908352d8a4SChris Mason slot = path->slots[0]; 4918352d8a4SChris Mason } 4928352d8a4SChris Mason btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); 4938352d8a4SChris Mason if (btrfs_key_type(&key) != BTRFS_DEV_ITEM_KEY) { 4948352d8a4SChris Mason path->slots[0]++; 4958352d8a4SChris Mason continue; 4968352d8a4SChris Mason } 4978352d8a4SChris Mason dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); 4988352d8a4SChris Mason printk("found key %Lu %Lu\n", key.objectid, key.offset); 499b4100d64SChris Mason if (btrfs_device_id(dev_item) != 500b4100d64SChris Mason btrfs_super_device_id(root->fs_info->disk_super)) { 501b4100d64SChris Mason ret = btrfs_open_disk(root, btrfs_device_id(dev_item), 502b4100d64SChris Mason key.objectid, key.offset, 5038352d8a4SChris Mason (char *)(dev_item + 1), 5048352d8a4SChris Mason btrfs_device_pathlen(dev_item)); 5058352d8a4SChris Mason BUG_ON(ret); 506b4100d64SChris Mason } 5078352d8a4SChris Mason path->slots[0]++; 5088352d8a4SChris Mason } 5098352d8a4SChris Mason btrfs_free_path(path); 5108352d8a4SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 5118352d8a4SChris Mason return 0; 5128352d8a4SChris Mason } 5138352d8a4SChris Mason 5142c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 515eb60ceacSChris Mason { 516e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 517e20d96d6SChris Mason GFP_NOFS); 5180bd93ba0SChris Mason struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root), 5190bd93ba0SChris Mason GFP_NOFS); 520e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 521e20d96d6SChris Mason GFP_NOFS); 522e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 523e20d96d6SChris Mason GFP_NOFS); 524eb60ceacSChris Mason int ret; 5252c90e5d6SChris Mason struct btrfs_super_block *disk_super; 5267eccb903SChris Mason struct dev_lookup *dev_lookup; 527eb60ceacSChris Mason 5288ef97622SChris Mason init_bit_radix(&fs_info->pinned_radix); 5298ef97622SChris Mason init_bit_radix(&fs_info->pending_del_radix); 5300f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 5317eccb903SChris Mason INIT_RADIX_TREE(&fs_info->dev_radix, GFP_NOFS); 5329078a3e1SChris Mason INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); 5338fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 5342c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 5359f5fae2fSChris Mason fs_info->running_transaction = NULL; 5369f5fae2fSChris Mason fs_info->tree_root = tree_root; 5379f5fae2fSChris Mason fs_info->extent_root = extent_root; 5380bd93ba0SChris Mason fs_info->dev_root = dev_root; 539e20d96d6SChris Mason fs_info->sb = sb; 540d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 541d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 5422c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 543d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 544d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 545e66f709bSChris Mason fs_info->do_barriers = 1; 546f2458e1dSChris Mason fs_info->extent_tree_insert_nr = 0; 547f2458e1dSChris Mason fs_info->extent_tree_prealloc_nr = 0; 5480f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 5490f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 5500f7d52f4SChris Mason sizeof(struct btrfs_key)); 55122b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 552d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 55387cbda5cSChris Mason fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); 55430ae8467SChris Mason spin_lock_init(&fs_info->hash_lock); 55530ae8467SChris Mason if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { 55687cbda5cSChris Mason printk("failed to allocate sha256 hash\n"); 55787cbda5cSChris Mason return NULL; 55887cbda5cSChris Mason } 55979154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 560d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 5619f5fae2fSChris Mason memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); 5623768f368SChris Mason 5630bd93ba0SChris Mason __setup_root(sb->s_blocksize, dev_root, 5640bd93ba0SChris Mason fs_info, BTRFS_DEV_TREE_OBJECTID); 5650bd93ba0SChris Mason 5662c90e5d6SChris Mason __setup_root(sb->s_blocksize, tree_root, 5672c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 5687eccb903SChris Mason 5697eccb903SChris Mason dev_lookup = kmalloc(sizeof(*dev_lookup), GFP_NOFS); 5707eccb903SChris Mason dev_lookup->block_start = 0; 5717eccb903SChris Mason dev_lookup->num_blocks = (u32)-2; 5727eccb903SChris Mason dev_lookup->bdev = sb->s_bdev; 573b4100d64SChris Mason dev_lookup->device_id = 0; 5747eccb903SChris Mason ret = radix_tree_insert(&fs_info->dev_radix, (u32)-2, dev_lookup); 5757eccb903SChris Mason BUG_ON(ret); 5762c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 5772c90e5d6SChris Mason BTRFS_SUPER_INFO_OFFSET / 5782c90e5d6SChris Mason sb->s_blocksize); 579d98237b3SChris Mason 5800f7d52f4SChris Mason if (!fs_info->sb_buffer) 581d98237b3SChris Mason return NULL; 582d98237b3SChris Mason disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; 5830f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 5842c90e5d6SChris Mason return NULL; 5850f7d52f4SChris Mason 5868352d8a4SChris Mason i_size_write(fs_info->btree_inode, 5878352d8a4SChris Mason btrfs_super_total_blocks(disk_super) << 5888352d8a4SChris Mason fs_info->btree_inode->i_blkbits); 5898352d8a4SChris Mason 5907eccb903SChris Mason radix_tree_delete(&fs_info->dev_radix, (u32)-2); 5917eccb903SChris Mason dev_lookup->block_start = btrfs_super_device_block_start(disk_super); 5927eccb903SChris Mason dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); 593b4100d64SChris Mason dev_lookup->device_id = btrfs_super_device_id(disk_super); 594b4100d64SChris Mason 5957eccb903SChris Mason ret = radix_tree_insert(&fs_info->dev_radix, 5967eccb903SChris Mason dev_lookup->block_start + 5978352d8a4SChris Mason dev_lookup->num_blocks - 1, dev_lookup); 5987eccb903SChris Mason BUG_ON(ret); 5997eccb903SChris Mason 600d98237b3SChris Mason fs_info->disk_super = disk_super; 6018352d8a4SChris Mason 6020bd93ba0SChris Mason dev_root->node = read_tree_block(tree_root, 6030bd93ba0SChris Mason btrfs_super_device_root(disk_super)); 6048352d8a4SChris Mason 6058352d8a4SChris Mason ret = read_device_info(dev_root); 6068352d8a4SChris Mason BUG_ON(ret); 6078352d8a4SChris Mason 608e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 609e20d96d6SChris Mason btrfs_super_root(disk_super)); 6103768f368SChris Mason BUG_ON(!tree_root->node); 6113768f368SChris Mason 6122c90e5d6SChris Mason mutex_lock(&fs_info->fs_mutex); 6132c90e5d6SChris Mason ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, 614e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 6153768f368SChris Mason BUG_ON(ret); 6163768f368SChris Mason 6179078a3e1SChris Mason btrfs_read_block_groups(extent_root); 6189078a3e1SChris Mason 6190f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 620d6e4a428SChris Mason memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); 621d6e4a428SChris Mason kobj_set_kset_s(fs_info, btrfs_subsys); 622d6e4a428SChris Mason kobject_set_name(&fs_info->kobj, "%s", sb->s_id); 623d6e4a428SChris Mason kobject_register(&fs_info->kobj); 6245be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 6250f7d52f4SChris Mason return tree_root; 626eb60ceacSChris Mason } 627eb60ceacSChris Mason 628e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 62979154b1bSChris Mason *root) 630cfaa7295SChris Mason { 631e66f709bSChris Mason int ret; 632d5719762SChris Mason struct buffer_head *bh = root->fs_info->sb_buffer; 6332c90e5d6SChris Mason 634d5719762SChris Mason btrfs_set_super_root(root->fs_info->disk_super, 6357eccb903SChris Mason bh_blocknr(root->fs_info->tree_root->node)); 636d5719762SChris Mason lock_buffer(bh); 6372c90e5d6SChris Mason WARN_ON(atomic_read(&bh->b_count) < 1); 638d5719762SChris Mason clear_buffer_dirty(bh); 63987cbda5cSChris Mason csum_tree_block(root, bh, 0); 640d5719762SChris Mason bh->b_end_io = end_buffer_write_sync; 641d5719762SChris Mason get_bh(bh); 642e66f709bSChris Mason if (root->fs_info->do_barriers) 643e66f709bSChris Mason ret = submit_bh(WRITE_BARRIER, bh); 644e66f709bSChris Mason else 645e66f709bSChris Mason ret = submit_bh(WRITE, bh); 646e66f709bSChris Mason if (ret == -EOPNOTSUPP) { 647e66f709bSChris Mason set_buffer_uptodate(bh); 648e66f709bSChris Mason root->fs_info->do_barriers = 0; 649e66f709bSChris Mason ret = submit_bh(WRITE, bh); 650e66f709bSChris Mason } 651d5719762SChris Mason wait_on_buffer(bh); 652d5719762SChris Mason if (!buffer_uptodate(bh)) { 653d5719762SChris Mason WARN_ON(1); 654d5719762SChris Mason return -EIO; 655cfaa7295SChris Mason } 656cfaa7295SChris Mason return 0; 657cfaa7295SChris Mason } 658cfaa7295SChris Mason 6592619ba1fSChris Mason static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 6602619ba1fSChris Mason { 6612619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 6622619ba1fSChris Mason (unsigned long)root->root_key.objectid); 6632619ba1fSChris Mason if (root->inode) 6642619ba1fSChris Mason iput(root->inode); 6652619ba1fSChris Mason if (root->node) 6662619ba1fSChris Mason brelse(root->node); 6672619ba1fSChris Mason if (root->commit_root) 6682619ba1fSChris Mason brelse(root->commit_root); 6692619ba1fSChris Mason kfree(root); 6702619ba1fSChris Mason return 0; 6712619ba1fSChris Mason } 6722619ba1fSChris Mason 6730f7d52f4SChris Mason int del_fs_roots(struct btrfs_fs_info *fs_info) 6740f7d52f4SChris Mason { 6750f7d52f4SChris Mason int ret; 6760f7d52f4SChris Mason struct btrfs_root *gang[8]; 6770f7d52f4SChris Mason int i; 6780f7d52f4SChris Mason 6790f7d52f4SChris Mason while(1) { 6800f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 6810f7d52f4SChris Mason (void **)gang, 0, 6820f7d52f4SChris Mason ARRAY_SIZE(gang)); 6830f7d52f4SChris Mason if (!ret) 6840f7d52f4SChris Mason break; 6852619ba1fSChris Mason for (i = 0; i < ret; i++) 6862619ba1fSChris Mason free_fs_root(fs_info, gang[i]); 6870f7d52f4SChris Mason } 6880f7d52f4SChris Mason return 0; 6890f7d52f4SChris Mason } 690b4100d64SChris Mason 6917eccb903SChris Mason static int free_dev_radix(struct btrfs_fs_info *fs_info) 6927eccb903SChris Mason { 6937eccb903SChris Mason struct dev_lookup *lookup[8]; 6947eccb903SChris Mason struct block_device *super_bdev = fs_info->sb->s_bdev; 6957eccb903SChris Mason int ret; 6967eccb903SChris Mason int i; 6977eccb903SChris Mason while(1) { 6987eccb903SChris Mason ret = radix_tree_gang_lookup(&fs_info->dev_radix, 6997eccb903SChris Mason (void **)lookup, 0, 7007eccb903SChris Mason ARRAY_SIZE(lookup)); 7017eccb903SChris Mason if (!ret) 7027eccb903SChris Mason break; 7037eccb903SChris Mason for (i = 0; i < ret; i++) { 7047eccb903SChris Mason if (lookup[i]->bdev != super_bdev) 7057eccb903SChris Mason close_bdev_excl(lookup[i]->bdev); 7067eccb903SChris Mason radix_tree_delete(&fs_info->dev_radix, 7077eccb903SChris Mason lookup[i]->block_start + 7088352d8a4SChris Mason lookup[i]->num_blocks - 1); 7097eccb903SChris Mason kfree(lookup[i]); 7107eccb903SChris Mason } 7117eccb903SChris Mason } 7127eccb903SChris Mason return 0; 7137eccb903SChris Mason } 7140f7d52f4SChris Mason 715e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 716eb60ceacSChris Mason { 7173768f368SChris Mason int ret; 718e089f05cSChris Mason struct btrfs_trans_handle *trans; 7190f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 720e089f05cSChris Mason 7210f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 72279154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 72379154b1bSChris Mason btrfs_commit_transaction(trans, root); 72479154b1bSChris Mason /* run commit again to drop the original snapshot */ 72579154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 72679154b1bSChris Mason btrfs_commit_transaction(trans, root); 72779154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 7289f5fae2fSChris Mason BUG_ON(ret); 72979154b1bSChris Mason write_ctree_super(NULL, root); 7300f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 731ed2ff2cbSChris Mason 7320f7d52f4SChris Mason if (fs_info->extent_root->node) 7330f7d52f4SChris Mason btrfs_block_release(fs_info->extent_root, 7340f7d52f4SChris Mason fs_info->extent_root->node); 7350bd93ba0SChris Mason if (fs_info->dev_root->node) 7360bd93ba0SChris Mason btrfs_block_release(fs_info->dev_root, 7370bd93ba0SChris Mason fs_info->dev_root->node); 7380f7d52f4SChris Mason if (fs_info->tree_root->node) 7390f7d52f4SChris Mason btrfs_block_release(fs_info->tree_root, 7400f7d52f4SChris Mason fs_info->tree_root->node); 7410f7d52f4SChris Mason btrfs_block_release(root, fs_info->sb_buffer); 7420f7d52f4SChris Mason crypto_free_hash(fs_info->hash_tfm); 7430f7d52f4SChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 7440f7d52f4SChris Mason iput(fs_info->btree_inode); 7457eccb903SChris Mason 7467eccb903SChris Mason free_dev_radix(fs_info); 7479078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 7480f7d52f4SChris Mason del_fs_roots(fs_info); 7490f7d52f4SChris Mason kfree(fs_info->extent_root); 7500f7d52f4SChris Mason kfree(fs_info->tree_root); 7510f7d52f4SChris Mason kobject_unregister(&fs_info->kobj); 752eb60ceacSChris Mason return 0; 753eb60ceacSChris Mason } 754eb60ceacSChris Mason 755e20d96d6SChris Mason void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) 756eb60ceacSChris Mason { 7577cfcc17eSChris Mason brelse(buf); 758eb60ceacSChris Mason } 759eb60ceacSChris Mason 760