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> 835b7e476SChris Mason #include <linux/writeback.h> 9eb60ceacSChris Mason #include "ctree.h" 10eb60ceacSChris Mason #include "disk-io.h" 11e089f05cSChris Mason #include "transaction.h" 120f7d52f4SChris Mason #include "btrfs_inode.h" 13eb60ceacSChris Mason 147eccb903SChris Mason struct dev_lookup { 157eccb903SChris Mason u64 block_start; 167eccb903SChris Mason u64 num_blocks; 17b4100d64SChris Mason u64 device_id; 187eccb903SChris Mason struct block_device *bdev; 197eccb903SChris Mason }; 207eccb903SChris Mason 218352d8a4SChris Mason int btrfs_insert_dev_radix(struct btrfs_root *root, 228352d8a4SChris Mason struct block_device *bdev, 23b4100d64SChris Mason u64 device_id, 248352d8a4SChris Mason u64 block_start, 258352d8a4SChris Mason u64 num_blocks) 268352d8a4SChris Mason { 278352d8a4SChris Mason struct dev_lookup *lookup; 288352d8a4SChris Mason int ret; 298352d8a4SChris Mason 308352d8a4SChris Mason lookup = kmalloc(sizeof(*lookup), GFP_NOFS); 318352d8a4SChris Mason if (!lookup) 328352d8a4SChris Mason return -ENOMEM; 338352d8a4SChris Mason lookup->block_start = block_start; 348352d8a4SChris Mason lookup->num_blocks = num_blocks; 358352d8a4SChris Mason lookup->bdev = bdev; 36b4100d64SChris Mason lookup->device_id = device_id; 378352d8a4SChris Mason 388352d8a4SChris Mason ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + 398352d8a4SChris Mason num_blocks - 1, lookup); 408352d8a4SChris Mason return ret; 418352d8a4SChris Mason } 428352d8a4SChris Mason 437eccb903SChris Mason u64 bh_blocknr(struct buffer_head *bh) 447eccb903SChris Mason { 457eccb903SChris Mason int blkbits = bh->b_page->mapping->host->i_blkbits; 467eccb903SChris Mason u64 blocknr = bh->b_page->index << (PAGE_CACHE_SHIFT - blkbits); 477eccb903SChris Mason unsigned long offset; 487eccb903SChris Mason 497eccb903SChris Mason if (PageHighMem(bh->b_page)) 507eccb903SChris Mason offset = (unsigned long)bh->b_data; 517eccb903SChris Mason else 527eccb903SChris Mason offset = bh->b_data - (char *)page_address(bh->b_page); 537eccb903SChris Mason blocknr += offset >> (PAGE_CACHE_SHIFT - blkbits); 547eccb903SChris Mason return blocknr; 557eccb903SChris Mason } 567eccb903SChris Mason 57e20d96d6SChris Mason static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) 58eb60ceacSChris Mason { 59e20d96d6SChris Mason struct btrfs_node *node = btrfs_buffer_node(buf); 607eccb903SChris Mason if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { 618352d8a4SChris Mason printk(KERN_CRIT "bh_blocknr(buf) is %Lu, header is %Lu\n", 628352d8a4SChris Mason bh_blocknr(buf), btrfs_header_blocknr(&node->header)); 639a8dd150SChris Mason BUG(); 64d98237b3SChris Mason } 659a8dd150SChris Mason return 0; 66eb60ceacSChris Mason } 67eb60ceacSChris Mason 68d98237b3SChris Mason struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) 69ed2ff2cbSChris Mason { 70d98237b3SChris Mason struct address_space *mapping = root->fs_info->btree_inode->i_mapping; 71d98237b3SChris Mason int blockbits = root->fs_info->sb->s_blocksize_bits; 72d98237b3SChris Mason unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); 73d98237b3SChris Mason struct page *page; 74d98237b3SChris Mason struct buffer_head *bh; 75d98237b3SChris Mason struct buffer_head *head; 76d98237b3SChris Mason struct buffer_head *ret = NULL; 77d98237b3SChris Mason 782c90e5d6SChris Mason 79d98237b3SChris Mason page = find_lock_page(mapping, index); 80d98237b3SChris Mason if (!page) 81d98237b3SChris Mason return NULL; 82d98237b3SChris Mason 83d98237b3SChris Mason if (!page_has_buffers(page)) 84d98237b3SChris Mason goto out_unlock; 85d98237b3SChris Mason 86d98237b3SChris Mason head = page_buffers(page); 87d98237b3SChris Mason bh = head; 88d98237b3SChris Mason do { 897eccb903SChris Mason if (buffer_mapped(bh) && bh_blocknr(bh) == blocknr) { 90d98237b3SChris Mason ret = bh; 91d98237b3SChris Mason get_bh(bh); 92d98237b3SChris Mason goto out_unlock; 93d98237b3SChris Mason } 94d98237b3SChris Mason bh = bh->b_this_page; 95d98237b3SChris Mason } while (bh != head); 96d98237b3SChris Mason out_unlock: 97d98237b3SChris Mason unlock_page(page); 98d98237b3SChris Mason page_cache_release(page); 99d98237b3SChris Mason return ret; 100ed2ff2cbSChris Mason } 101ed2ff2cbSChris Mason 1028352d8a4SChris Mason int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, 1037eccb903SChris Mason u64 logical) 1047eccb903SChris Mason { 1057eccb903SChris Mason struct dev_lookup *lookup[2]; 1067eccb903SChris Mason 1077eccb903SChris Mason int ret; 1087eccb903SChris Mason 109236454dfSChris Mason if (logical == 0) { 110236454dfSChris Mason bh->b_bdev = NULL; 111236454dfSChris Mason bh->b_blocknr = 0; 112236454dfSChris Mason set_buffer_mapped(bh); 113236454dfSChris Mason return 0; 114236454dfSChris Mason } 1157eccb903SChris Mason root = root->fs_info->dev_root; 1167eccb903SChris Mason ret = radix_tree_gang_lookup(&root->fs_info->dev_radix, 1177eccb903SChris Mason (void **)lookup, 1187eccb903SChris Mason (unsigned long)logical, 1197eccb903SChris Mason ARRAY_SIZE(lookup)); 1207eccb903SChris Mason if (ret == 0 || lookup[0]->block_start > logical || 1217eccb903SChris Mason lookup[0]->block_start + lookup[0]->num_blocks <= logical) { 1227eccb903SChris Mason ret = -ENOENT; 1237eccb903SChris Mason goto out; 1247eccb903SChris Mason } 1257eccb903SChris Mason bh->b_bdev = lookup[0]->bdev; 1267eccb903SChris Mason bh->b_blocknr = logical - lookup[0]->block_start; 1277eccb903SChris Mason set_buffer_mapped(bh); 1287eccb903SChris Mason ret = 0; 1297eccb903SChris Mason out: 1307eccb903SChris Mason return ret; 1317eccb903SChris Mason } 1327eccb903SChris Mason 133d98237b3SChris Mason struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, 134d98237b3SChris Mason u64 blocknr) 135eb60ceacSChris Mason { 136d98237b3SChris Mason struct address_space *mapping = root->fs_info->btree_inode->i_mapping; 137d98237b3SChris Mason int blockbits = root->fs_info->sb->s_blocksize_bits; 138d98237b3SChris Mason unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); 139d98237b3SChris Mason struct page *page; 140d98237b3SChris Mason struct buffer_head *bh; 141d98237b3SChris Mason struct buffer_head *head; 142d98237b3SChris Mason struct buffer_head *ret = NULL; 1437eccb903SChris Mason int err; 144d98237b3SChris Mason u64 first_block = index << (PAGE_CACHE_SHIFT - blockbits); 14522b0ebdaSChris Mason 146d98237b3SChris Mason page = grab_cache_page(mapping, index); 147d98237b3SChris Mason if (!page) 148d98237b3SChris Mason return NULL; 149d98237b3SChris Mason 150d98237b3SChris Mason if (!page_has_buffers(page)) 151d98237b3SChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 0); 152d98237b3SChris Mason head = page_buffers(page); 153d98237b3SChris Mason bh = head; 154d98237b3SChris Mason do { 155d98237b3SChris Mason if (!buffer_mapped(bh)) { 1568352d8a4SChris Mason err = btrfs_map_bh_to_logical(root, bh, first_block); 1577eccb903SChris Mason BUG_ON(err); 158e20d96d6SChris Mason } 1597eccb903SChris Mason if (bh_blocknr(bh) == blocknr) { 160d98237b3SChris Mason ret = bh; 161d98237b3SChris Mason get_bh(bh); 162d98237b3SChris Mason goto out_unlock; 163d98237b3SChris Mason } 164d98237b3SChris Mason bh = bh->b_this_page; 165d98237b3SChris Mason first_block++; 166d98237b3SChris Mason } while (bh != head); 167d98237b3SChris Mason out_unlock: 168d98237b3SChris Mason unlock_page(page); 16922b0ebdaSChris Mason if (ret) 17022b0ebdaSChris Mason touch_buffer(ret); 171d98237b3SChris Mason page_cache_release(page); 172d98237b3SChris Mason return ret; 173d98237b3SChris Mason } 174d98237b3SChris Mason 175d98237b3SChris Mason static int btree_get_block(struct inode *inode, sector_t iblock, 176d98237b3SChris Mason struct buffer_head *bh, int create) 177d98237b3SChris Mason { 1787eccb903SChris Mason int err; 1797eccb903SChris Mason struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; 1808352d8a4SChris Mason err = btrfs_map_bh_to_logical(root, bh, iblock); 1817eccb903SChris Mason return err; 182d98237b3SChris Mason } 183d98237b3SChris Mason 184f254e52cSChris Mason int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, 185f254e52cSChris Mason char *result) 18687cbda5cSChris Mason { 18787cbda5cSChris Mason struct scatterlist sg; 18887cbda5cSChris Mason struct crypto_hash *tfm = root->fs_info->hash_tfm; 18987cbda5cSChris Mason struct hash_desc desc; 19087cbda5cSChris Mason int ret; 19187cbda5cSChris Mason 19287cbda5cSChris Mason desc.tfm = tfm; 19387cbda5cSChris Mason desc.flags = 0; 194f254e52cSChris Mason sg_init_one(&sg, data, len); 19587cbda5cSChris Mason spin_lock(&root->fs_info->hash_lock); 19622b0ebdaSChris Mason ret = crypto_hash_digest(&desc, &sg, 1, result); 19787cbda5cSChris Mason spin_unlock(&root->fs_info->hash_lock); 19887cbda5cSChris Mason if (ret) { 19987cbda5cSChris Mason printk("sha256 digest failed\n"); 20087cbda5cSChris Mason } 201f254e52cSChris Mason return ret; 202f254e52cSChris Mason } 203f254e52cSChris Mason static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, 204f254e52cSChris Mason int verify) 205f254e52cSChris Mason { 206f254e52cSChris Mason char result[BTRFS_CSUM_SIZE]; 207f254e52cSChris Mason int ret; 208f254e52cSChris Mason struct btrfs_node *node; 209f254e52cSChris Mason 210f254e52cSChris Mason ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE, 211f254e52cSChris Mason bh->b_size - BTRFS_CSUM_SIZE, result); 212f254e52cSChris Mason if (ret) 213f254e52cSChris Mason return ret; 21487cbda5cSChris Mason if (verify) { 215f254e52cSChris Mason if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) { 2167eccb903SChris Mason printk("checksum verify failed on %Lu\n", 2177eccb903SChris Mason bh_blocknr(bh)); 218f254e52cSChris Mason return 1; 219f254e52cSChris Mason } 220f254e52cSChris Mason } else { 221f254e52cSChris Mason node = btrfs_buffer_node(bh); 22222b0ebdaSChris Mason memcpy(node->header.csum, result, BTRFS_CSUM_SIZE); 223f254e52cSChris Mason } 22487cbda5cSChris Mason return 0; 22587cbda5cSChris Mason } 22687cbda5cSChris Mason 227d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 228d98237b3SChris Mason { 22987cbda5cSChris Mason struct buffer_head *bh; 2300f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 23187cbda5cSChris Mason struct buffer_head *head; 23287cbda5cSChris Mason if (!page_has_buffers(page)) { 23387cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 23487cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 23587cbda5cSChris Mason } 23687cbda5cSChris Mason head = page_buffers(page); 23787cbda5cSChris Mason bh = head; 23887cbda5cSChris Mason do { 23987cbda5cSChris Mason if (buffer_dirty(bh)) 24087cbda5cSChris Mason csum_tree_block(root, bh, 0); 24187cbda5cSChris Mason bh = bh->b_this_page; 24287cbda5cSChris Mason } while (bh != head); 243d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 244d98237b3SChris Mason } 245d98237b3SChris Mason 246d98237b3SChris Mason static int btree_readpage(struct file * file, struct page * page) 247d98237b3SChris Mason { 248d98237b3SChris Mason return block_read_full_page(page, btree_get_block); 249d98237b3SChris Mason } 250d98237b3SChris Mason 251d98237b3SChris Mason static struct address_space_operations btree_aops = { 252d98237b3SChris Mason .readpage = btree_readpage, 253d98237b3SChris Mason .writepage = btree_writepage, 254d98237b3SChris Mason .sync_page = block_sync_page, 255d98237b3SChris Mason }; 256123abc88SChris Mason 257090d1875SChris Mason int readahead_tree_block(struct btrfs_root *root, u64 blocknr) 258090d1875SChris Mason { 259090d1875SChris Mason struct buffer_head *bh = NULL; 260090d1875SChris Mason 261090d1875SChris Mason bh = btrfs_find_create_tree_block(root, blocknr); 262090d1875SChris Mason if (!bh) 263090d1875SChris Mason return 0; 264090d1875SChris Mason if (buffer_uptodate(bh)) 265090d1875SChris Mason goto done; 266090d1875SChris Mason if (test_set_buffer_locked(bh)) 267090d1875SChris Mason goto done; 268090d1875SChris Mason if (!buffer_uptodate(bh)) { 269090d1875SChris Mason get_bh(bh); 270090d1875SChris Mason bh->b_end_io = end_buffer_read_sync; 271090d1875SChris Mason submit_bh(READ, bh); 272090d1875SChris Mason } else { 273090d1875SChris Mason unlock_buffer(bh); 274090d1875SChris Mason } 275090d1875SChris Mason done: 276090d1875SChris Mason brelse(bh); 277090d1875SChris Mason return 0; 278090d1875SChris Mason } 279090d1875SChris Mason 280e20d96d6SChris Mason struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) 281e20d96d6SChris Mason { 282d98237b3SChris Mason struct buffer_head *bh = NULL; 283e20d96d6SChris Mason 284d98237b3SChris Mason bh = btrfs_find_create_tree_block(root, blocknr); 285d98237b3SChris Mason if (!bh) 286d98237b3SChris Mason return bh; 2879d64272cSChris Mason if (buffer_uptodate(bh)) 2889d64272cSChris Mason goto uptodate; 289d98237b3SChris Mason lock_buffer(bh); 290d98237b3SChris Mason if (!buffer_uptodate(bh)) { 291d98237b3SChris Mason get_bh(bh); 292d98237b3SChris Mason bh->b_end_io = end_buffer_read_sync; 293d98237b3SChris Mason submit_bh(READ, bh); 294d98237b3SChris Mason wait_on_buffer(bh); 295d98237b3SChris Mason if (!buffer_uptodate(bh)) 296d98237b3SChris Mason goto fail; 297d98237b3SChris Mason } else { 298d98237b3SChris Mason unlock_buffer(bh); 299d98237b3SChris Mason } 3009d64272cSChris Mason uptodate: 301090d1875SChris Mason if (!buffer_checked(bh)) { 302090d1875SChris Mason csum_tree_block(root, bh, 1); 303090d1875SChris Mason set_buffer_checked(bh); 304090d1875SChris Mason } 305d98237b3SChris Mason if (check_tree_block(root, bh)) 306cfaa7295SChris Mason BUG(); 307d98237b3SChris Mason return bh; 308d98237b3SChris Mason fail: 309d98237b3SChris Mason brelse(bh); 310d98237b3SChris Mason return NULL; 311eb60ceacSChris Mason } 312eb60ceacSChris Mason 313e089f05cSChris Mason int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 314e20d96d6SChris Mason struct buffer_head *buf) 315ed2ff2cbSChris Mason { 316d6025579SChris Mason WARN_ON(atomic_read(&buf->b_count) == 0); 317e20d96d6SChris Mason mark_buffer_dirty(buf); 318ed2ff2cbSChris Mason return 0; 319ed2ff2cbSChris Mason } 320ed2ff2cbSChris Mason 321e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 322e20d96d6SChris Mason struct buffer_head *buf) 323ed2ff2cbSChris Mason { 324d6025579SChris Mason WARN_ON(atomic_read(&buf->b_count) == 0); 325e20d96d6SChris Mason clear_buffer_dirty(buf); 326ed2ff2cbSChris Mason return 0; 327ed2ff2cbSChris Mason } 328ed2ff2cbSChris Mason 3292c90e5d6SChris Mason static int __setup_root(int blocksize, 3309f5fae2fSChris Mason struct btrfs_root *root, 3319f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 332e20d96d6SChris Mason u64 objectid) 333d97e63b6SChris Mason { 334cfaa7295SChris Mason root->node = NULL; 3350f7d52f4SChris Mason root->inode = NULL; 336a28ec197SChris Mason root->commit_root = NULL; 3372c90e5d6SChris Mason root->blocksize = blocksize; 338123abc88SChris Mason root->ref_cows = 0; 3399f5fae2fSChris Mason root->fs_info = fs_info; 3400f7d52f4SChris Mason root->objectid = objectid; 3410f7d52f4SChris Mason root->last_trans = 0; 3421b05da2eSChris Mason root->highest_inode = 0; 3431b05da2eSChris Mason root->last_inode_alloc = 0; 3443768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 3453768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 3464d775673SChris Mason root->root_key.objectid = objectid; 3473768f368SChris Mason return 0; 3483768f368SChris Mason } 3493768f368SChris Mason 3502c90e5d6SChris Mason static int find_and_setup_root(int blocksize, 3519f5fae2fSChris Mason struct btrfs_root *tree_root, 3529f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 3539f5fae2fSChris Mason u64 objectid, 354e20d96d6SChris Mason struct btrfs_root *root) 3553768f368SChris Mason { 3563768f368SChris Mason int ret; 3573768f368SChris Mason 3582c90e5d6SChris Mason __setup_root(blocksize, root, fs_info, objectid); 3593768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 3603768f368SChris Mason &root->root_item, &root->root_key); 3613768f368SChris Mason BUG_ON(ret); 3623768f368SChris Mason 3633768f368SChris Mason root->node = read_tree_block(root, 3643768f368SChris Mason btrfs_root_blocknr(&root->root_item)); 3653768f368SChris Mason BUG_ON(!root->node); 366d97e63b6SChris Mason return 0; 367d97e63b6SChris Mason } 368d97e63b6SChris Mason 3690f7d52f4SChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 3700f7d52f4SChris Mason struct btrfs_key *location) 3710f7d52f4SChris Mason { 3720f7d52f4SChris Mason struct btrfs_root *root; 3730f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 3740f7d52f4SChris Mason struct btrfs_path *path; 3750f7d52f4SChris Mason struct btrfs_leaf *l; 3761b05da2eSChris Mason u64 highest_inode; 3770f7d52f4SChris Mason int ret = 0; 3780f7d52f4SChris Mason 3790f7d52f4SChris Mason printk("read_fs_root looking for %Lu %Lu %u\n", location->objectid, location->offset, location->flags); 3802619ba1fSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 3812619ba1fSChris Mason (unsigned long)location->objectid); 3822619ba1fSChris Mason if (root) { 3832619ba1fSChris Mason printk("found %p in cache\n", root); 3842619ba1fSChris Mason return root; 3852619ba1fSChris Mason } 3860f7d52f4SChris Mason root = kmalloc(sizeof(*root), GFP_NOFS); 3870f7d52f4SChris Mason if (!root) { 3880f7d52f4SChris Mason printk("failed1\n"); 3890f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 3900f7d52f4SChris Mason } 3910f7d52f4SChris Mason if (location->offset == (u64)-1) { 3920f7d52f4SChris Mason ret = find_and_setup_root(fs_info->sb->s_blocksize, 3930f7d52f4SChris Mason fs_info->tree_root, fs_info, 3940f7d52f4SChris Mason location->objectid, root); 3950f7d52f4SChris Mason if (ret) { 3960f7d52f4SChris Mason printk("failed2\n"); 3970f7d52f4SChris Mason kfree(root); 3980f7d52f4SChris Mason return ERR_PTR(ret); 3990f7d52f4SChris Mason } 4000f7d52f4SChris Mason goto insert; 4010f7d52f4SChris Mason } 4020f7d52f4SChris Mason 4030f7d52f4SChris Mason __setup_root(fs_info->sb->s_blocksize, root, fs_info, 4040f7d52f4SChris Mason location->objectid); 4050f7d52f4SChris Mason 4060f7d52f4SChris Mason path = btrfs_alloc_path(); 4070f7d52f4SChris Mason BUG_ON(!path); 4080f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 4090f7d52f4SChris Mason if (ret != 0) { 4100f7d52f4SChris Mason printk("internal search_slot gives us %d\n", ret); 4110f7d52f4SChris Mason if (ret > 0) 4120f7d52f4SChris Mason ret = -ENOENT; 4130f7d52f4SChris Mason goto out; 4140f7d52f4SChris Mason } 4150f7d52f4SChris Mason l = btrfs_buffer_leaf(path->nodes[0]); 4160f7d52f4SChris Mason memcpy(&root->root_item, 4170f7d52f4SChris Mason btrfs_item_ptr(l, path->slots[0], struct btrfs_root_item), 4180f7d52f4SChris Mason sizeof(root->root_item)); 4190f7d52f4SChris Mason memcpy(&root->root_key, location, sizeof(*location)); 4200f7d52f4SChris Mason ret = 0; 4210f7d52f4SChris Mason out: 4220f7d52f4SChris Mason btrfs_release_path(root, path); 4230f7d52f4SChris Mason btrfs_free_path(path); 4240f7d52f4SChris Mason if (ret) { 4250f7d52f4SChris Mason kfree(root); 4260f7d52f4SChris Mason return ERR_PTR(ret); 4270f7d52f4SChris Mason } 4280f7d52f4SChris Mason root->node = read_tree_block(root, 4290f7d52f4SChris Mason btrfs_root_blocknr(&root->root_item)); 4300f7d52f4SChris Mason BUG_ON(!root->node); 4310f7d52f4SChris Mason insert: 4320f7d52f4SChris Mason printk("inserting %p\n", root); 4330f7d52f4SChris Mason root->ref_cows = 1; 4342619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 4352619ba1fSChris Mason (unsigned long)root->root_key.objectid, 4360f7d52f4SChris Mason root); 4370f7d52f4SChris Mason if (ret) { 4380f7d52f4SChris Mason printk("radix_tree_insert gives us %d\n", ret); 4390f7d52f4SChris Mason brelse(root->node); 4400f7d52f4SChris Mason kfree(root); 4410f7d52f4SChris Mason return ERR_PTR(ret); 4420f7d52f4SChris Mason } 4431b05da2eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 4441b05da2eSChris Mason if (ret == 0) { 4451b05da2eSChris Mason root->highest_inode = highest_inode; 4461b05da2eSChris Mason root->last_inode_alloc = highest_inode; 4471b05da2eSChris Mason printk("highest inode is %Lu\n", highest_inode); 4481b05da2eSChris Mason } 4490f7d52f4SChris Mason printk("all worked\n"); 4500f7d52f4SChris Mason return root; 4510f7d52f4SChris Mason } 4520f7d52f4SChris Mason 453b4100d64SChris Mason static int btrfs_open_disk(struct btrfs_root *root, u64 device_id, 454b4100d64SChris Mason u64 block_start, u64 num_blocks, 4558352d8a4SChris Mason char *filename, int name_len) 4568352d8a4SChris Mason { 4578352d8a4SChris Mason char *null_filename; 4588352d8a4SChris Mason struct block_device *bdev; 4598352d8a4SChris Mason int ret; 4608352d8a4SChris Mason 4618352d8a4SChris Mason null_filename = kmalloc(name_len + 1, GFP_NOFS); 4628352d8a4SChris Mason if (!null_filename) 4638352d8a4SChris Mason return -ENOMEM; 4648352d8a4SChris Mason memcpy(null_filename, filename, name_len); 4658352d8a4SChris Mason null_filename[name_len] = '\0'; 4668352d8a4SChris Mason 4678352d8a4SChris Mason bdev = open_bdev_excl(null_filename, O_RDWR, root->fs_info->sb); 4688352d8a4SChris Mason if (IS_ERR(bdev)) { 4698352d8a4SChris Mason ret = PTR_ERR(bdev); 4708352d8a4SChris Mason goto out; 4718352d8a4SChris Mason } 4728352d8a4SChris Mason set_blocksize(bdev, root->fs_info->sb->s_blocksize); 473b4100d64SChris Mason ret = btrfs_insert_dev_radix(root, bdev, device_id, 474b4100d64SChris Mason block_start, num_blocks); 4758352d8a4SChris Mason BUG_ON(ret); 4768352d8a4SChris Mason ret = 0; 4778352d8a4SChris Mason out: 4788352d8a4SChris Mason kfree(null_filename); 4798352d8a4SChris Mason return ret; 4808352d8a4SChris Mason } 4818352d8a4SChris Mason 4828352d8a4SChris Mason static int read_device_info(struct btrfs_root *root) 4838352d8a4SChris Mason { 4848352d8a4SChris Mason struct btrfs_path *path; 4858352d8a4SChris Mason int ret; 4868352d8a4SChris Mason struct btrfs_key key; 4878352d8a4SChris Mason struct btrfs_leaf *leaf; 4888352d8a4SChris Mason struct btrfs_device_item *dev_item; 4898352d8a4SChris Mason int nritems; 4908352d8a4SChris Mason int slot; 4918352d8a4SChris Mason 4928352d8a4SChris Mason root = root->fs_info->dev_root; 4938352d8a4SChris Mason 4948352d8a4SChris Mason path = btrfs_alloc_path(); 4958352d8a4SChris Mason if (!path) 4968352d8a4SChris Mason return -ENOMEM; 4978352d8a4SChris Mason key.objectid = 0; 4988352d8a4SChris Mason key.offset = 0; 4998352d8a4SChris Mason key.flags = 0; 5008352d8a4SChris Mason btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); 5018352d8a4SChris Mason 5028352d8a4SChris Mason mutex_lock(&root->fs_info->fs_mutex); 5038352d8a4SChris Mason ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 5048352d8a4SChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 5058352d8a4SChris Mason nritems = btrfs_header_nritems(&leaf->header); 5068352d8a4SChris Mason while(1) { 5078352d8a4SChris Mason slot = path->slots[0]; 5088352d8a4SChris Mason if (slot >= nritems) { 5098352d8a4SChris Mason ret = btrfs_next_leaf(root, path); 5108352d8a4SChris Mason if (ret) 5118352d8a4SChris Mason break; 5128352d8a4SChris Mason leaf = btrfs_buffer_leaf(path->nodes[0]); 5138352d8a4SChris Mason nritems = btrfs_header_nritems(&leaf->header); 5148352d8a4SChris Mason slot = path->slots[0]; 5158352d8a4SChris Mason } 5168352d8a4SChris Mason btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); 5178352d8a4SChris Mason if (btrfs_key_type(&key) != BTRFS_DEV_ITEM_KEY) { 5188352d8a4SChris Mason path->slots[0]++; 5198352d8a4SChris Mason continue; 5208352d8a4SChris Mason } 5218352d8a4SChris Mason dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); 5228352d8a4SChris Mason printk("found key %Lu %Lu\n", key.objectid, key.offset); 523b4100d64SChris Mason if (btrfs_device_id(dev_item) != 524b4100d64SChris Mason btrfs_super_device_id(root->fs_info->disk_super)) { 525b4100d64SChris Mason ret = btrfs_open_disk(root, btrfs_device_id(dev_item), 526b4100d64SChris Mason key.objectid, key.offset, 5278352d8a4SChris Mason (char *)(dev_item + 1), 5288352d8a4SChris Mason btrfs_device_pathlen(dev_item)); 5298352d8a4SChris Mason BUG_ON(ret); 530b4100d64SChris Mason } 5318352d8a4SChris Mason path->slots[0]++; 5328352d8a4SChris Mason } 5338352d8a4SChris Mason btrfs_free_path(path); 5348352d8a4SChris Mason mutex_unlock(&root->fs_info->fs_mutex); 5358352d8a4SChris Mason return 0; 5368352d8a4SChris Mason } 5378352d8a4SChris Mason 5382c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 539eb60ceacSChris Mason { 540e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 541e20d96d6SChris Mason GFP_NOFS); 5420bd93ba0SChris Mason struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root), 5430bd93ba0SChris Mason GFP_NOFS); 544e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 545e20d96d6SChris Mason GFP_NOFS); 546e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 547e20d96d6SChris Mason GFP_NOFS); 548eb60ceacSChris Mason int ret; 5492c90e5d6SChris Mason struct btrfs_super_block *disk_super; 5507eccb903SChris Mason struct dev_lookup *dev_lookup; 551eb60ceacSChris Mason 5528ef97622SChris Mason init_bit_radix(&fs_info->pinned_radix); 5538ef97622SChris Mason init_bit_radix(&fs_info->pending_del_radix); 5540f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 5557eccb903SChris Mason INIT_RADIX_TREE(&fs_info->dev_radix, GFP_NOFS); 5569078a3e1SChris Mason INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); 5578fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 5582c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 5599f5fae2fSChris Mason fs_info->running_transaction = NULL; 5609f5fae2fSChris Mason fs_info->tree_root = tree_root; 5619f5fae2fSChris Mason fs_info->extent_root = extent_root; 5620bd93ba0SChris Mason fs_info->dev_root = dev_root; 563e20d96d6SChris Mason fs_info->sb = sb; 564d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 565d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 5662c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 567d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 568d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 569e66f709bSChris Mason fs_info->do_barriers = 1; 570f2458e1dSChris Mason fs_info->extent_tree_insert_nr = 0; 571f2458e1dSChris Mason fs_info->extent_tree_prealloc_nr = 0; 5720f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 5730f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 5740f7d52f4SChris Mason sizeof(struct btrfs_key)); 57522b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 576d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 57787cbda5cSChris Mason fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); 57830ae8467SChris Mason spin_lock_init(&fs_info->hash_lock); 57930ae8467SChris Mason if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { 58087cbda5cSChris Mason printk("failed to allocate sha256 hash\n"); 58187cbda5cSChris Mason return NULL; 58287cbda5cSChris Mason } 58379154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 584d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 585cd1bc465SChris Mason fs_info->block_group_cache = NULL; 5863768f368SChris Mason 5870bd93ba0SChris Mason __setup_root(sb->s_blocksize, dev_root, 5880bd93ba0SChris Mason fs_info, BTRFS_DEV_TREE_OBJECTID); 5890bd93ba0SChris Mason 5902c90e5d6SChris Mason __setup_root(sb->s_blocksize, tree_root, 5912c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 5927eccb903SChris Mason 5937eccb903SChris Mason dev_lookup = kmalloc(sizeof(*dev_lookup), GFP_NOFS); 5947eccb903SChris Mason dev_lookup->block_start = 0; 5957eccb903SChris Mason dev_lookup->num_blocks = (u32)-2; 5967eccb903SChris Mason dev_lookup->bdev = sb->s_bdev; 597b4100d64SChris Mason dev_lookup->device_id = 0; 5987eccb903SChris Mason ret = radix_tree_insert(&fs_info->dev_radix, (u32)-2, dev_lookup); 5997eccb903SChris Mason BUG_ON(ret); 6002c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 6012c90e5d6SChris Mason BTRFS_SUPER_INFO_OFFSET / 6022c90e5d6SChris Mason sb->s_blocksize); 603d98237b3SChris Mason 6040f7d52f4SChris Mason if (!fs_info->sb_buffer) 605d98237b3SChris Mason return NULL; 606d98237b3SChris Mason disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; 6070f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 6082c90e5d6SChris Mason return NULL; 6090f7d52f4SChris Mason 6108352d8a4SChris Mason i_size_write(fs_info->btree_inode, 6118352d8a4SChris Mason btrfs_super_total_blocks(disk_super) << 6128352d8a4SChris Mason fs_info->btree_inode->i_blkbits); 6138352d8a4SChris Mason 6147eccb903SChris Mason radix_tree_delete(&fs_info->dev_radix, (u32)-2); 6157eccb903SChris Mason dev_lookup->block_start = btrfs_super_device_block_start(disk_super); 6167eccb903SChris Mason dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); 617b4100d64SChris Mason dev_lookup->device_id = btrfs_super_device_id(disk_super); 618b4100d64SChris Mason 6197eccb903SChris Mason ret = radix_tree_insert(&fs_info->dev_radix, 6207eccb903SChris Mason dev_lookup->block_start + 6218352d8a4SChris Mason dev_lookup->num_blocks - 1, dev_lookup); 6227eccb903SChris Mason BUG_ON(ret); 6237eccb903SChris Mason 624d98237b3SChris Mason fs_info->disk_super = disk_super; 6258352d8a4SChris Mason 6260bd93ba0SChris Mason dev_root->node = read_tree_block(tree_root, 6270bd93ba0SChris Mason btrfs_super_device_root(disk_super)); 6288352d8a4SChris Mason 6298352d8a4SChris Mason ret = read_device_info(dev_root); 6308352d8a4SChris Mason BUG_ON(ret); 6318352d8a4SChris Mason 632e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 633e20d96d6SChris Mason btrfs_super_root(disk_super)); 6343768f368SChris Mason BUG_ON(!tree_root->node); 6353768f368SChris Mason 6362c90e5d6SChris Mason mutex_lock(&fs_info->fs_mutex); 6372c90e5d6SChris Mason ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, 638e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 6393768f368SChris Mason BUG_ON(ret); 6403768f368SChris Mason 6419078a3e1SChris Mason btrfs_read_block_groups(extent_root); 6429078a3e1SChris Mason 6430f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 644d6e4a428SChris Mason memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); 645d6e4a428SChris Mason kobj_set_kset_s(fs_info, btrfs_subsys); 646d6e4a428SChris Mason kobject_set_name(&fs_info->kobj, "%s", sb->s_id); 647d6e4a428SChris Mason kobject_register(&fs_info->kobj); 6485be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 6490f7d52f4SChris Mason return tree_root; 650eb60ceacSChris Mason } 651eb60ceacSChris Mason 652e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 65379154b1bSChris Mason *root) 654cfaa7295SChris Mason { 655e66f709bSChris Mason int ret; 656d5719762SChris Mason struct buffer_head *bh = root->fs_info->sb_buffer; 6572c90e5d6SChris Mason 658d5719762SChris Mason btrfs_set_super_root(root->fs_info->disk_super, 6597eccb903SChris Mason bh_blocknr(root->fs_info->tree_root->node)); 660d5719762SChris Mason lock_buffer(bh); 6612c90e5d6SChris Mason WARN_ON(atomic_read(&bh->b_count) < 1); 662d5719762SChris Mason clear_buffer_dirty(bh); 66387cbda5cSChris Mason csum_tree_block(root, bh, 0); 664d5719762SChris Mason bh->b_end_io = end_buffer_write_sync; 665d5719762SChris Mason get_bh(bh); 666e66f709bSChris Mason if (root->fs_info->do_barriers) 667e66f709bSChris Mason ret = submit_bh(WRITE_BARRIER, bh); 668e66f709bSChris Mason else 669e66f709bSChris Mason ret = submit_bh(WRITE, bh); 670e66f709bSChris Mason if (ret == -EOPNOTSUPP) { 671e66f709bSChris Mason set_buffer_uptodate(bh); 672e66f709bSChris Mason root->fs_info->do_barriers = 0; 673e66f709bSChris Mason ret = submit_bh(WRITE, bh); 674e66f709bSChris Mason } 675d5719762SChris Mason wait_on_buffer(bh); 676d5719762SChris Mason if (!buffer_uptodate(bh)) { 677d5719762SChris Mason WARN_ON(1); 678d5719762SChris Mason return -EIO; 679cfaa7295SChris Mason } 680cfaa7295SChris Mason return 0; 681cfaa7295SChris Mason } 682cfaa7295SChris Mason 6832619ba1fSChris Mason static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 6842619ba1fSChris Mason { 6852619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 6862619ba1fSChris Mason (unsigned long)root->root_key.objectid); 6872619ba1fSChris Mason if (root->inode) 6882619ba1fSChris Mason iput(root->inode); 6892619ba1fSChris Mason if (root->node) 6902619ba1fSChris Mason brelse(root->node); 6912619ba1fSChris Mason if (root->commit_root) 6922619ba1fSChris Mason brelse(root->commit_root); 6932619ba1fSChris Mason kfree(root); 6942619ba1fSChris Mason return 0; 6952619ba1fSChris Mason } 6962619ba1fSChris Mason 69735b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 6980f7d52f4SChris Mason { 6990f7d52f4SChris Mason int ret; 7000f7d52f4SChris Mason struct btrfs_root *gang[8]; 7010f7d52f4SChris Mason int i; 7020f7d52f4SChris Mason 7030f7d52f4SChris Mason while(1) { 7040f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 7050f7d52f4SChris Mason (void **)gang, 0, 7060f7d52f4SChris Mason ARRAY_SIZE(gang)); 7070f7d52f4SChris Mason if (!ret) 7080f7d52f4SChris Mason break; 7092619ba1fSChris Mason for (i = 0; i < ret; i++) 7102619ba1fSChris Mason free_fs_root(fs_info, gang[i]); 7110f7d52f4SChris Mason } 7120f7d52f4SChris Mason return 0; 7130f7d52f4SChris Mason } 714b4100d64SChris Mason 7157eccb903SChris Mason static int free_dev_radix(struct btrfs_fs_info *fs_info) 7167eccb903SChris Mason { 7177eccb903SChris Mason struct dev_lookup *lookup[8]; 7187eccb903SChris Mason struct block_device *super_bdev = fs_info->sb->s_bdev; 7197eccb903SChris Mason int ret; 7207eccb903SChris Mason int i; 7217eccb903SChris Mason while(1) { 7227eccb903SChris Mason ret = radix_tree_gang_lookup(&fs_info->dev_radix, 7237eccb903SChris Mason (void **)lookup, 0, 7247eccb903SChris Mason ARRAY_SIZE(lookup)); 7257eccb903SChris Mason if (!ret) 7267eccb903SChris Mason break; 7277eccb903SChris Mason for (i = 0; i < ret; i++) { 7287eccb903SChris Mason if (lookup[i]->bdev != super_bdev) 7297eccb903SChris Mason close_bdev_excl(lookup[i]->bdev); 7307eccb903SChris Mason radix_tree_delete(&fs_info->dev_radix, 7317eccb903SChris Mason lookup[i]->block_start + 7328352d8a4SChris Mason lookup[i]->num_blocks - 1); 7337eccb903SChris Mason kfree(lookup[i]); 7347eccb903SChris Mason } 7357eccb903SChris Mason } 7367eccb903SChris Mason return 0; 7377eccb903SChris Mason } 7380f7d52f4SChris Mason 739e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 740eb60ceacSChris Mason { 7413768f368SChris Mason int ret; 742e089f05cSChris Mason struct btrfs_trans_handle *trans; 7430f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 744e089f05cSChris Mason 7450f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 74679154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 74779154b1bSChris Mason btrfs_commit_transaction(trans, root); 74879154b1bSChris Mason /* run commit again to drop the original snapshot */ 74979154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 75079154b1bSChris Mason btrfs_commit_transaction(trans, root); 75179154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 7529f5fae2fSChris Mason BUG_ON(ret); 75379154b1bSChris Mason write_ctree_super(NULL, root); 7540f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 755ed2ff2cbSChris Mason 7560f7d52f4SChris Mason if (fs_info->extent_root->node) 7570f7d52f4SChris Mason btrfs_block_release(fs_info->extent_root, 7580f7d52f4SChris Mason fs_info->extent_root->node); 7590bd93ba0SChris Mason if (fs_info->dev_root->node) 7600bd93ba0SChris Mason btrfs_block_release(fs_info->dev_root, 7610bd93ba0SChris Mason fs_info->dev_root->node); 7620f7d52f4SChris Mason if (fs_info->tree_root->node) 7630f7d52f4SChris Mason btrfs_block_release(fs_info->tree_root, 7640f7d52f4SChris Mason fs_info->tree_root->node); 7650f7d52f4SChris Mason btrfs_block_release(root, fs_info->sb_buffer); 7660f7d52f4SChris Mason crypto_free_hash(fs_info->hash_tfm); 7670f7d52f4SChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 7680f7d52f4SChris Mason iput(fs_info->btree_inode); 7697eccb903SChris Mason 7707eccb903SChris Mason free_dev_radix(fs_info); 7719078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 7720f7d52f4SChris Mason del_fs_roots(fs_info); 7730f7d52f4SChris Mason kfree(fs_info->extent_root); 7740f7d52f4SChris Mason kfree(fs_info->tree_root); 7750f7d52f4SChris Mason kobject_unregister(&fs_info->kobj); 776eb60ceacSChris Mason return 0; 777eb60ceacSChris Mason } 778eb60ceacSChris Mason 779e20d96d6SChris Mason void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) 780eb60ceacSChris Mason { 7817cfcc17eSChris Mason brelse(buf); 782eb60ceacSChris Mason } 783eb60ceacSChris Mason 78435b7e476SChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root) 78535b7e476SChris Mason { 78635b7e476SChris Mason balance_dirty_pages_ratelimited(root->fs_info->btree_inode->i_mapping); 78735b7e476SChris Mason } 788