16cbd5570SChris Mason /* 26cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 36cbd5570SChris Mason * 46cbd5570SChris Mason * This program is free software; you can redistribute it and/or 56cbd5570SChris Mason * modify it under the terms of the GNU General Public 66cbd5570SChris Mason * License v2 as published by the Free Software Foundation. 76cbd5570SChris Mason * 86cbd5570SChris Mason * This program is distributed in the hope that it will be useful, 96cbd5570SChris Mason * but WITHOUT ANY WARRANTY; without even the implied warranty of 106cbd5570SChris Mason * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 116cbd5570SChris Mason * General Public License for more details. 126cbd5570SChris Mason * 136cbd5570SChris Mason * You should have received a copy of the GNU General Public 146cbd5570SChris Mason * License along with this program; if not, write to the 156cbd5570SChris Mason * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 166cbd5570SChris Mason * Boston, MA 021110-1307, USA. 176cbd5570SChris Mason */ 186cbd5570SChris Mason 19e20d96d6SChris Mason #include <linux/fs.h> 20d98237b3SChris Mason #include <linux/blkdev.h> 2111bd143fSChris Mason #include <linux/crc32c.h> 2287cbda5cSChris Mason #include <linux/scatterlist.h> 2322b0ebdaSChris Mason #include <linux/swap.h> 240f7d52f4SChris Mason #include <linux/radix-tree.h> 2535b7e476SChris Mason #include <linux/writeback.h> 265f39d397SChris Mason #include <linux/buffer_head.h> // for block_sync_page 27eb60ceacSChris Mason #include "ctree.h" 28eb60ceacSChris Mason #include "disk-io.h" 29e089f05cSChris Mason #include "transaction.h" 300f7d52f4SChris Mason #include "btrfs_inode.h" 31db94535dSChris Mason #include "print-tree.h" 32eb60ceacSChris Mason 335f39d397SChris Mason #if 0 345f39d397SChris Mason static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) 357eccb903SChris Mason { 365f39d397SChris Mason if (extent_buffer_blocknr(buf) != btrfs_header_blocknr(buf)) { 375f39d397SChris Mason printk(KERN_CRIT "buf blocknr(buf) is %llu, header is %llu\n", 385f39d397SChris Mason (unsigned long long)extent_buffer_blocknr(buf), 395f39d397SChris Mason (unsigned long long)btrfs_header_blocknr(buf)); 4039279cc3SChris Mason return 1; 41d98237b3SChris Mason } 429a8dd150SChris Mason return 0; 43eb60ceacSChris Mason } 445f39d397SChris Mason #endif 45eb60ceacSChris Mason 46d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops; 470da5468fSChris Mason 485f39d397SChris Mason struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 49db94535dSChris Mason u64 bytenr, u32 blocksize) 50eb60ceacSChris Mason { 515f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 52f510cfecSChris Mason struct extent_buffer *eb; 53d1310b2eSChris Mason eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 54db94535dSChris Mason bytenr, blocksize, GFP_NOFS); 55f510cfecSChris Mason return eb; 56e20d96d6SChris Mason } 575f39d397SChris Mason 585f39d397SChris Mason struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, 59db94535dSChris Mason u64 bytenr, u32 blocksize) 605f39d397SChris Mason { 615f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 62f510cfecSChris Mason struct extent_buffer *eb; 63db94535dSChris Mason 64d1310b2eSChris Mason eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 6519c00ddcSChris Mason bytenr, blocksize, NULL, GFP_NOFS); 66f510cfecSChris Mason return eb; 67d98237b3SChris Mason } 685f39d397SChris Mason 695f39d397SChris Mason struct extent_map *btree_get_extent(struct inode *inode, struct page *page, 70d1310b2eSChris Mason size_t page_offset, u64 start, u64 len, 715f39d397SChris Mason int create) 725f39d397SChris Mason { 735f39d397SChris Mason struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 745f39d397SChris Mason struct extent_map *em; 755f39d397SChris Mason int ret; 765f39d397SChris Mason 775f39d397SChris Mason again: 78d1310b2eSChris Mason spin_lock(&em_tree->lock); 79d1310b2eSChris Mason em = lookup_extent_mapping(em_tree, start, len); 80d1310b2eSChris Mason spin_unlock(&em_tree->lock); 815f39d397SChris Mason if (em) { 825f39d397SChris Mason goto out; 835f39d397SChris Mason } 845f39d397SChris Mason em = alloc_extent_map(GFP_NOFS); 855f39d397SChris Mason if (!em) { 865f39d397SChris Mason em = ERR_PTR(-ENOMEM); 875f39d397SChris Mason goto out; 885f39d397SChris Mason } 895f39d397SChris Mason em->start = 0; 90d1310b2eSChris Mason em->len = i_size_read(inode); 915f39d397SChris Mason em->block_start = 0; 925f39d397SChris Mason em->bdev = inode->i_sb->s_bdev; 93d1310b2eSChris Mason 94d1310b2eSChris Mason spin_lock(&em_tree->lock); 955f39d397SChris Mason ret = add_extent_mapping(em_tree, em); 96d1310b2eSChris Mason spin_unlock(&em_tree->lock); 97d1310b2eSChris Mason 985f39d397SChris Mason if (ret == -EEXIST) { 995f39d397SChris Mason free_extent_map(em); 1005f39d397SChris Mason em = NULL; 1015f39d397SChris Mason goto again; 1025f39d397SChris Mason } else if (ret) { 1035f39d397SChris Mason em = ERR_PTR(ret); 1045f39d397SChris Mason } 1055f39d397SChris Mason out: 1065f39d397SChris Mason return em; 1075f39d397SChris Mason } 1085f39d397SChris Mason 10919c00ddcSChris Mason u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 11019c00ddcSChris Mason { 11119c00ddcSChris Mason return crc32c(seed, data, len); 11219c00ddcSChris Mason } 11319c00ddcSChris Mason 11419c00ddcSChris Mason void btrfs_csum_final(u32 crc, char *result) 11519c00ddcSChris Mason { 11619c00ddcSChris Mason *(__le32 *)result = ~cpu_to_le32(crc); 11719c00ddcSChris Mason } 11819c00ddcSChris Mason 11919c00ddcSChris Mason static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 12019c00ddcSChris Mason int verify) 12119c00ddcSChris Mason { 12219c00ddcSChris Mason char result[BTRFS_CRC32_SIZE]; 12319c00ddcSChris Mason unsigned long len; 12419c00ddcSChris Mason unsigned long cur_len; 12519c00ddcSChris Mason unsigned long offset = BTRFS_CSUM_SIZE; 12619c00ddcSChris Mason char *map_token = NULL; 12719c00ddcSChris Mason char *kaddr; 12819c00ddcSChris Mason unsigned long map_start; 12919c00ddcSChris Mason unsigned long map_len; 13019c00ddcSChris Mason int err; 13119c00ddcSChris Mason u32 crc = ~(u32)0; 13219c00ddcSChris Mason 13319c00ddcSChris Mason len = buf->len - offset; 13419c00ddcSChris Mason while(len > 0) { 13519c00ddcSChris Mason err = map_private_extent_buffer(buf, offset, 32, 13619c00ddcSChris Mason &map_token, &kaddr, 13719c00ddcSChris Mason &map_start, &map_len, KM_USER0); 13819c00ddcSChris Mason if (err) { 13919c00ddcSChris Mason printk("failed to map extent buffer! %lu\n", 14019c00ddcSChris Mason offset); 14119c00ddcSChris Mason return 1; 14219c00ddcSChris Mason } 14319c00ddcSChris Mason cur_len = min(len, map_len - (offset - map_start)); 14419c00ddcSChris Mason crc = btrfs_csum_data(root, kaddr + offset - map_start, 14519c00ddcSChris Mason crc, cur_len); 14619c00ddcSChris Mason len -= cur_len; 14719c00ddcSChris Mason offset += cur_len; 14819c00ddcSChris Mason unmap_extent_buffer(buf, map_token, KM_USER0); 14919c00ddcSChris Mason } 15019c00ddcSChris Mason btrfs_csum_final(crc, result); 15119c00ddcSChris Mason 15219c00ddcSChris Mason if (verify) { 153e4204dedSChris Mason int from_this_trans = 0; 154e4204dedSChris Mason 155e4204dedSChris Mason if (root->fs_info->running_transaction && 156e4204dedSChris Mason btrfs_header_generation(buf) == 157e4204dedSChris Mason root->fs_info->running_transaction->transid) 158e4204dedSChris Mason from_this_trans = 1; 159e4204dedSChris Mason 160e4204dedSChris Mason /* FIXME, this is not good */ 161e4204dedSChris Mason if (from_this_trans == 0 && 162e4204dedSChris Mason memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 163e4204dedSChris Mason u32 val; 164e4204dedSChris Mason u32 found = 0; 165e4204dedSChris Mason memcpy(&found, result, BTRFS_CRC32_SIZE); 166e4204dedSChris Mason 167e4204dedSChris Mason read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE); 168e4204dedSChris Mason printk("btrfs: %s checksum verify failed on %llu " 169e4204dedSChris Mason "wanted %X found %X from_this_trans %d\n", 17019c00ddcSChris Mason root->fs_info->sb->s_id, 171e4204dedSChris Mason buf->start, val, found, from_this_trans); 17219c00ddcSChris Mason return 1; 17319c00ddcSChris Mason } 17419c00ddcSChris Mason } else { 17519c00ddcSChris Mason write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 17619c00ddcSChris Mason } 17719c00ddcSChris Mason return 0; 17819c00ddcSChris Mason } 17919c00ddcSChris Mason 18019c00ddcSChris Mason 18119c00ddcSChris Mason int csum_dirty_buffer(struct btrfs_root *root, struct page *page) 18219c00ddcSChris Mason { 183d1310b2eSChris Mason struct extent_io_tree *tree; 18435ebb934SChris Mason u64 start = (u64)page->index << PAGE_CACHE_SHIFT; 18519c00ddcSChris Mason u64 found_start; 18619c00ddcSChris Mason int found_level; 18719c00ddcSChris Mason unsigned long len; 18819c00ddcSChris Mason struct extent_buffer *eb; 189d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 19019c00ddcSChris Mason 19119c00ddcSChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 19219c00ddcSChris Mason goto out; 19319c00ddcSChris Mason if (!page->private) 19419c00ddcSChris Mason goto out; 19519c00ddcSChris Mason len = page->private >> 2; 19619c00ddcSChris Mason if (len == 0) { 19719c00ddcSChris Mason WARN_ON(1); 19819c00ddcSChris Mason } 19919c00ddcSChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 20019c00ddcSChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1); 201e18e4809SChris Mason btrfs_clear_buffer_defrag(eb); 20219c00ddcSChris Mason found_start = btrfs_header_bytenr(eb); 20319c00ddcSChris Mason if (found_start != start) { 20419c00ddcSChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 20519c00ddcSChris Mason start, found_start, len); 20655c69072SChris Mason WARN_ON(1); 20755c69072SChris Mason goto err; 20855c69072SChris Mason } 20955c69072SChris Mason if (eb->first_page != page) { 21055c69072SChris Mason printk("bad first page %lu %lu\n", eb->first_page->index, 21155c69072SChris Mason page->index); 21255c69072SChris Mason WARN_ON(1); 21355c69072SChris Mason goto err; 21455c69072SChris Mason } 21555c69072SChris Mason if (!PageUptodate(page)) { 21655c69072SChris Mason printk("csum not up to date page %lu\n", page->index); 21755c69072SChris Mason WARN_ON(1); 21855c69072SChris Mason goto err; 21919c00ddcSChris Mason } 22019c00ddcSChris Mason found_level = btrfs_header_level(eb); 22119c00ddcSChris Mason csum_tree_block(root, eb, 0); 22255c69072SChris Mason err: 22319c00ddcSChris Mason free_extent_buffer(eb); 22419c00ddcSChris Mason out: 22519c00ddcSChris Mason return 0; 22619c00ddcSChris Mason } 22719c00ddcSChris Mason 2280da5468fSChris Mason static int btree_writepage_io_hook(struct page *page, u64 start, u64 end) 2290da5468fSChris Mason { 2300da5468fSChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 2310da5468fSChris Mason 2320da5468fSChris Mason csum_dirty_buffer(root, page); 2330da5468fSChris Mason return 0; 2340da5468fSChris Mason } 2350da5468fSChris Mason 2365f39d397SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 2375f39d397SChris Mason { 238d1310b2eSChris Mason struct extent_io_tree *tree; 239d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 2405f39d397SChris Mason return extent_write_full_page(tree, page, btree_get_extent, wbc); 2415f39d397SChris Mason } 2420da5468fSChris Mason 2430da5468fSChris Mason static int btree_writepages(struct address_space *mapping, 2440da5468fSChris Mason struct writeback_control *wbc) 2450da5468fSChris Mason { 246d1310b2eSChris Mason struct extent_io_tree *tree; 247d1310b2eSChris Mason tree = &BTRFS_I(mapping->host)->io_tree; 248d8d5f3e1SChris Mason if (wbc->sync_mode == WB_SYNC_NONE) { 249793955bcSChris Mason u64 num_dirty; 250793955bcSChris Mason u64 start = 0; 251793955bcSChris Mason unsigned long thresh = 96 * 1024 * 1024; 252448d640bSChris Mason 253448d640bSChris Mason if (wbc->for_kupdate) 254448d640bSChris Mason return 0; 255448d640bSChris Mason 256ca664626SChris Mason if (current_is_pdflush()) { 257ca664626SChris Mason thresh = 96 * 1024 * 1024; 258ca664626SChris Mason } else { 259ca664626SChris Mason thresh = 8 * 1024 * 1024; 260ca664626SChris Mason } 2611832a6d5SChris Mason num_dirty = count_range_bits(tree, &start, (u64)-1, 2621832a6d5SChris Mason thresh, EXTENT_DIRTY); 263793955bcSChris Mason if (num_dirty < thresh) { 264793955bcSChris Mason return 0; 265793955bcSChris Mason } 266793955bcSChris Mason } 2670da5468fSChris Mason return extent_writepages(tree, mapping, btree_get_extent, wbc); 2680da5468fSChris Mason } 2690da5468fSChris Mason 2705f39d397SChris Mason int btree_readpage(struct file *file, struct page *page) 2715f39d397SChris Mason { 272d1310b2eSChris Mason struct extent_io_tree *tree; 273d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 2745f39d397SChris Mason return extent_read_full_page(tree, page, btree_get_extent); 2755f39d397SChris Mason } 2765f39d397SChris Mason 2775f39d397SChris Mason static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags) 2785f39d397SChris Mason { 279d1310b2eSChris Mason struct extent_io_tree *tree; 280d1310b2eSChris Mason struct extent_map_tree *map; 2815f39d397SChris Mason int ret; 2825f39d397SChris Mason 283d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 284d1310b2eSChris Mason map = &BTRFS_I(page->mapping->host)->extent_tree; 285d1310b2eSChris Mason ret = try_release_extent_mapping(map, tree, page); 2865f39d397SChris Mason if (ret == 1) { 2875f39d397SChris Mason ClearPagePrivate(page); 2885f39d397SChris Mason set_page_private(page, 0); 289d98237b3SChris Mason page_cache_release(page); 2905f39d397SChris Mason } 291d98237b3SChris Mason return ret; 292d98237b3SChris Mason } 293d98237b3SChris Mason 2945f39d397SChris Mason static void btree_invalidatepage(struct page *page, unsigned long offset) 295d98237b3SChris Mason { 296d1310b2eSChris Mason struct extent_io_tree *tree; 297d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 2985f39d397SChris Mason extent_invalidatepage(tree, page, offset); 2995f39d397SChris Mason btree_releasepage(page, GFP_NOFS); 300d98237b3SChris Mason } 301d98237b3SChris Mason 3025f39d397SChris Mason #if 0 303d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 304d98237b3SChris Mason { 30587cbda5cSChris Mason struct buffer_head *bh; 3060f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 30787cbda5cSChris Mason struct buffer_head *head; 30887cbda5cSChris Mason if (!page_has_buffers(page)) { 30987cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 31087cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 31187cbda5cSChris Mason } 31287cbda5cSChris Mason head = page_buffers(page); 31387cbda5cSChris Mason bh = head; 31487cbda5cSChris Mason do { 31587cbda5cSChris Mason if (buffer_dirty(bh)) 31687cbda5cSChris Mason csum_tree_block(root, bh, 0); 31787cbda5cSChris Mason bh = bh->b_this_page; 31887cbda5cSChris Mason } while (bh != head); 319d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 320d98237b3SChris Mason } 3215f39d397SChris Mason #endif 322d98237b3SChris Mason 323d98237b3SChris Mason static struct address_space_operations btree_aops = { 324d98237b3SChris Mason .readpage = btree_readpage, 325d98237b3SChris Mason .writepage = btree_writepage, 3260da5468fSChris Mason .writepages = btree_writepages, 3275f39d397SChris Mason .releasepage = btree_releasepage, 3285f39d397SChris Mason .invalidatepage = btree_invalidatepage, 329d98237b3SChris Mason .sync_page = block_sync_page, 330d98237b3SChris Mason }; 331123abc88SChris Mason 332db94535dSChris Mason int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) 333090d1875SChris Mason { 3345f39d397SChris Mason struct extent_buffer *buf = NULL; 3355f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 336de428b63SChris Mason int ret = 0; 337090d1875SChris Mason 338db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3395f39d397SChris Mason if (!buf) 340090d1875SChris Mason return 0; 341d1310b2eSChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 34219c00ddcSChris Mason buf, 0, 0); 3435f39d397SChris Mason free_extent_buffer(buf); 344de428b63SChris Mason return ret; 345090d1875SChris Mason } 346090d1875SChris Mason 347db94535dSChris Mason struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 348db94535dSChris Mason u32 blocksize) 349e20d96d6SChris Mason { 3505f39d397SChris Mason struct extent_buffer *buf = NULL; 3515f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 352d1310b2eSChris Mason struct extent_io_tree *io_tree; 353e4204dedSChris Mason u64 end; 35419c00ddcSChris Mason int ret; 35519c00ddcSChris Mason 356d1310b2eSChris Mason io_tree = &BTRFS_I(btree_inode)->io_tree; 357e20d96d6SChris Mason 358db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3595f39d397SChris Mason if (!buf) 360d98237b3SChris Mason return NULL; 361d1310b2eSChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1); 362e4204dedSChris Mason 363e4204dedSChris Mason if (buf->flags & EXTENT_CSUM) 36419c00ddcSChris Mason return buf; 365e4204dedSChris Mason 366e4204dedSChris Mason end = buf->start + PAGE_CACHE_SIZE - 1; 367d1310b2eSChris Mason if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { 36819c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 36919c00ddcSChris Mason return buf; 37019c00ddcSChris Mason } 371e4204dedSChris Mason 372d1310b2eSChris Mason lock_extent(io_tree, buf->start, end, GFP_NOFS); 373e4204dedSChris Mason 374d1310b2eSChris Mason if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { 375e4204dedSChris Mason buf->flags |= EXTENT_CSUM; 376e4204dedSChris Mason goto out_unlock; 377e4204dedSChris Mason } 378e4204dedSChris Mason 37919c00ddcSChris Mason ret = csum_tree_block(root, buf, 1); 380d1310b2eSChris Mason set_extent_bits(io_tree, buf->start, end, EXTENT_CSUM, GFP_NOFS); 38119c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 382e4204dedSChris Mason 383e4204dedSChris Mason out_unlock: 384d1310b2eSChris Mason unlock_extent(io_tree, buf->start, end, GFP_NOFS); 3855f39d397SChris Mason return buf; 386eb60ceacSChris Mason } 387eb60ceacSChris Mason 388e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 3895f39d397SChris Mason struct extent_buffer *buf) 390ed2ff2cbSChris Mason { 3915f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 39255c69072SChris Mason if (btrfs_header_generation(buf) == 39355c69072SChris Mason root->fs_info->running_transaction->transid) 394d1310b2eSChris Mason clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, 39555c69072SChris Mason buf); 3965f39d397SChris Mason return 0; 3975f39d397SChris Mason } 3985f39d397SChris Mason 3995f39d397SChris Mason int wait_on_tree_block_writeback(struct btrfs_root *root, 4005f39d397SChris Mason struct extent_buffer *buf) 4015f39d397SChris Mason { 4025f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 403d1310b2eSChris Mason wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->io_tree, 4045f39d397SChris Mason buf); 4055f39d397SChris Mason return 0; 4065f39d397SChris Mason } 4075f39d397SChris Mason 408db94535dSChris Mason static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 40987ee04ebSChris Mason u32 stripesize, struct btrfs_root *root, 4109f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 411e20d96d6SChris Mason u64 objectid) 412d97e63b6SChris Mason { 413cfaa7295SChris Mason root->node = NULL; 4140f7d52f4SChris Mason root->inode = NULL; 415a28ec197SChris Mason root->commit_root = NULL; 416db94535dSChris Mason root->sectorsize = sectorsize; 417db94535dSChris Mason root->nodesize = nodesize; 418db94535dSChris Mason root->leafsize = leafsize; 41987ee04ebSChris Mason root->stripesize = stripesize; 420123abc88SChris Mason root->ref_cows = 0; 4219f5fae2fSChris Mason root->fs_info = fs_info; 4220f7d52f4SChris Mason root->objectid = objectid; 4230f7d52f4SChris Mason root->last_trans = 0; 4241b05da2eSChris Mason root->highest_inode = 0; 4251b05da2eSChris Mason root->last_inode_alloc = 0; 42658176a96SJosef Bacik root->name = NULL; 4274313b399SChris Mason root->in_sysfs = 0; 4283768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 4293768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 4306702ed49SChris Mason memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 43158176a96SJosef Bacik memset(&root->root_kobj, 0, sizeof(root->root_kobj)); 43258176a96SJosef Bacik init_completion(&root->kobj_unregister); 4336702ed49SChris Mason root->defrag_running = 0; 4346702ed49SChris Mason root->defrag_level = 0; 4354d775673SChris Mason root->root_key.objectid = objectid; 4363768f368SChris Mason return 0; 4373768f368SChris Mason } 4383768f368SChris Mason 439db94535dSChris Mason static int find_and_setup_root(struct btrfs_root *tree_root, 4409f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 4419f5fae2fSChris Mason u64 objectid, 442e20d96d6SChris Mason struct btrfs_root *root) 4433768f368SChris Mason { 4443768f368SChris Mason int ret; 445db94535dSChris Mason u32 blocksize; 4463768f368SChris Mason 447db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 44887ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 44987ee04ebSChris Mason root, fs_info, objectid); 4503768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 4513768f368SChris Mason &root->root_item, &root->root_key); 4523768f368SChris Mason BUG_ON(ret); 4533768f368SChris Mason 454db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 455db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 456db94535dSChris Mason blocksize); 4573768f368SChris Mason BUG_ON(!root->node); 458d97e63b6SChris Mason return 0; 459d97e63b6SChris Mason } 460d97e63b6SChris Mason 4615eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 4620f7d52f4SChris Mason struct btrfs_key *location) 4630f7d52f4SChris Mason { 4640f7d52f4SChris Mason struct btrfs_root *root; 4650f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 4660f7d52f4SChris Mason struct btrfs_path *path; 4675f39d397SChris Mason struct extent_buffer *l; 4681b05da2eSChris Mason u64 highest_inode; 469db94535dSChris Mason u32 blocksize; 4700f7d52f4SChris Mason int ret = 0; 4710f7d52f4SChris Mason 4725eda7b5eSChris Mason root = kzalloc(sizeof(*root), GFP_NOFS); 4730cf6c620SChris Mason if (!root) 4740f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 4750f7d52f4SChris Mason if (location->offset == (u64)-1) { 476db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 4770f7d52f4SChris Mason location->objectid, root); 4780f7d52f4SChris Mason if (ret) { 4790f7d52f4SChris Mason kfree(root); 4800f7d52f4SChris Mason return ERR_PTR(ret); 4810f7d52f4SChris Mason } 4820f7d52f4SChris Mason goto insert; 4830f7d52f4SChris Mason } 4840f7d52f4SChris Mason 485db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 48687ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 48787ee04ebSChris Mason root, fs_info, location->objectid); 4880f7d52f4SChris Mason 4890f7d52f4SChris Mason path = btrfs_alloc_path(); 4900f7d52f4SChris Mason BUG_ON(!path); 4910f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 4920f7d52f4SChris Mason if (ret != 0) { 4930f7d52f4SChris Mason if (ret > 0) 4940f7d52f4SChris Mason ret = -ENOENT; 4950f7d52f4SChris Mason goto out; 4960f7d52f4SChris Mason } 4975f39d397SChris Mason l = path->nodes[0]; 4985f39d397SChris Mason read_extent_buffer(l, &root->root_item, 4995f39d397SChris Mason btrfs_item_ptr_offset(l, path->slots[0]), 5000f7d52f4SChris Mason sizeof(root->root_item)); 50144b36eb2SYan Zheng memcpy(&root->root_key, location, sizeof(*location)); 5020f7d52f4SChris Mason ret = 0; 5030f7d52f4SChris Mason out: 5040f7d52f4SChris Mason btrfs_release_path(root, path); 5050f7d52f4SChris Mason btrfs_free_path(path); 5060f7d52f4SChris Mason if (ret) { 5070f7d52f4SChris Mason kfree(root); 5080f7d52f4SChris Mason return ERR_PTR(ret); 5090f7d52f4SChris Mason } 510db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 511db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 512db94535dSChris Mason blocksize); 5130f7d52f4SChris Mason BUG_ON(!root->node); 5140f7d52f4SChris Mason insert: 5150f7d52f4SChris Mason root->ref_cows = 1; 5165eda7b5eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 5175eda7b5eSChris Mason if (ret == 0) { 5185eda7b5eSChris Mason root->highest_inode = highest_inode; 5195eda7b5eSChris Mason root->last_inode_alloc = highest_inode; 5205eda7b5eSChris Mason } 5215eda7b5eSChris Mason return root; 5225eda7b5eSChris Mason } 5235eda7b5eSChris Mason 524dc17ff8fSChris Mason struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, 525dc17ff8fSChris Mason u64 root_objectid) 526dc17ff8fSChris Mason { 527dc17ff8fSChris Mason struct btrfs_root *root; 528dc17ff8fSChris Mason 529dc17ff8fSChris Mason if (root_objectid == BTRFS_ROOT_TREE_OBJECTID) 530dc17ff8fSChris Mason return fs_info->tree_root; 531dc17ff8fSChris Mason if (root_objectid == BTRFS_EXTENT_TREE_OBJECTID) 532dc17ff8fSChris Mason return fs_info->extent_root; 533dc17ff8fSChris Mason 534dc17ff8fSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 535dc17ff8fSChris Mason (unsigned long)root_objectid); 536dc17ff8fSChris Mason return root; 537dc17ff8fSChris Mason } 538dc17ff8fSChris Mason 539edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, 540edbd8d4eSChris Mason struct btrfs_key *location) 5415eda7b5eSChris Mason { 5425eda7b5eSChris Mason struct btrfs_root *root; 5435eda7b5eSChris Mason int ret; 5445eda7b5eSChris Mason 545edbd8d4eSChris Mason if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) 546edbd8d4eSChris Mason return fs_info->tree_root; 547edbd8d4eSChris Mason if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) 548edbd8d4eSChris Mason return fs_info->extent_root; 549edbd8d4eSChris Mason 5505eda7b5eSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 5515eda7b5eSChris Mason (unsigned long)location->objectid); 5525eda7b5eSChris Mason if (root) 5535eda7b5eSChris Mason return root; 5545eda7b5eSChris Mason 5555eda7b5eSChris Mason root = btrfs_read_fs_root_no_radix(fs_info, location); 5565eda7b5eSChris Mason if (IS_ERR(root)) 5575eda7b5eSChris Mason return root; 5582619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 5592619ba1fSChris Mason (unsigned long)root->root_key.objectid, 5600f7d52f4SChris Mason root); 5610f7d52f4SChris Mason if (ret) { 5625f39d397SChris Mason free_extent_buffer(root->node); 5630f7d52f4SChris Mason kfree(root); 5640f7d52f4SChris Mason return ERR_PTR(ret); 5650f7d52f4SChris Mason } 566edbd8d4eSChris Mason ret = btrfs_find_dead_roots(fs_info->tree_root, 567edbd8d4eSChris Mason root->root_key.objectid, root); 568edbd8d4eSChris Mason BUG_ON(ret); 569edbd8d4eSChris Mason 570edbd8d4eSChris Mason return root; 571edbd8d4eSChris Mason } 572edbd8d4eSChris Mason 573edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 574edbd8d4eSChris Mason struct btrfs_key *location, 575edbd8d4eSChris Mason const char *name, int namelen) 576edbd8d4eSChris Mason { 577edbd8d4eSChris Mason struct btrfs_root *root; 578edbd8d4eSChris Mason int ret; 579edbd8d4eSChris Mason 580edbd8d4eSChris Mason root = btrfs_read_fs_root_no_name(fs_info, location); 581edbd8d4eSChris Mason if (!root) 582edbd8d4eSChris Mason return NULL; 58358176a96SJosef Bacik 5844313b399SChris Mason if (root->in_sysfs) 5854313b399SChris Mason return root; 5864313b399SChris Mason 58758176a96SJosef Bacik ret = btrfs_set_root_name(root, name, namelen); 58858176a96SJosef Bacik if (ret) { 5895f39d397SChris Mason free_extent_buffer(root->node); 59058176a96SJosef Bacik kfree(root); 59158176a96SJosef Bacik return ERR_PTR(ret); 59258176a96SJosef Bacik } 59358176a96SJosef Bacik 59458176a96SJosef Bacik ret = btrfs_sysfs_add_root(root); 59558176a96SJosef Bacik if (ret) { 5965f39d397SChris Mason free_extent_buffer(root->node); 59758176a96SJosef Bacik kfree(root->name); 59858176a96SJosef Bacik kfree(root); 59958176a96SJosef Bacik return ERR_PTR(ret); 60058176a96SJosef Bacik } 6014313b399SChris Mason root->in_sysfs = 1; 6020f7d52f4SChris Mason return root; 6030f7d52f4SChris Mason } 60419c00ddcSChris Mason #if 0 60519c00ddcSChris Mason static int add_hasher(struct btrfs_fs_info *info, char *type) { 60619c00ddcSChris Mason struct btrfs_hasher *hasher; 6070f7d52f4SChris Mason 60819c00ddcSChris Mason hasher = kmalloc(sizeof(*hasher), GFP_NOFS); 60919c00ddcSChris Mason if (!hasher) 61019c00ddcSChris Mason return -ENOMEM; 61119c00ddcSChris Mason hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC); 61219c00ddcSChris Mason if (!hasher->hash_tfm) { 61319c00ddcSChris Mason kfree(hasher); 61419c00ddcSChris Mason return -EINVAL; 61519c00ddcSChris Mason } 61619c00ddcSChris Mason spin_lock(&info->hash_lock); 61719c00ddcSChris Mason list_add(&hasher->list, &info->hashers); 61819c00ddcSChris Mason spin_unlock(&info->hash_lock); 61919c00ddcSChris Mason return 0; 62019c00ddcSChris Mason } 62119c00ddcSChris Mason #endif 6222c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 623eb60ceacSChris Mason { 624db94535dSChris Mason u32 sectorsize; 625db94535dSChris Mason u32 nodesize; 626db94535dSChris Mason u32 leafsize; 627db94535dSChris Mason u32 blocksize; 62887ee04ebSChris Mason u32 stripesize; 629e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 630e20d96d6SChris Mason GFP_NOFS); 631e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 632e20d96d6SChris Mason GFP_NOFS); 633e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 634e20d96d6SChris Mason GFP_NOFS); 635eb60ceacSChris Mason int ret; 63639279cc3SChris Mason int err = -EIO; 6372c90e5d6SChris Mason struct btrfs_super_block *disk_super; 638eb60ceacSChris Mason 63939279cc3SChris Mason if (!extent_root || !tree_root || !fs_info) { 64039279cc3SChris Mason err = -ENOMEM; 64139279cc3SChris Mason goto fail; 64239279cc3SChris Mason } 6430f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 6448fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 645facda1e7SChris Mason INIT_LIST_HEAD(&fs_info->dead_roots); 64619c00ddcSChris Mason INIT_LIST_HEAD(&fs_info->hashers); 64719c00ddcSChris Mason spin_lock_init(&fs_info->hash_lock); 6481832a6d5SChris Mason spin_lock_init(&fs_info->delalloc_lock); 649cee36a03SChris Mason spin_lock_init(&fs_info->new_trans_lock); 65019c00ddcSChris Mason 65158176a96SJosef Bacik memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj)); 65258176a96SJosef Bacik init_completion(&fs_info->kobj_unregister); 6532c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 6549f5fae2fSChris Mason fs_info->running_transaction = NULL; 65515ee9bc7SJosef Bacik fs_info->last_trans_committed = 0; 6569f5fae2fSChris Mason fs_info->tree_root = tree_root; 6579f5fae2fSChris Mason fs_info->extent_root = extent_root; 658e20d96d6SChris Mason fs_info->sb = sb; 659e2008b61SChris Mason fs_info->throttles = 0; 660b6cda9bcSChris Mason fs_info->mount_opt = 0; 661c59f8951SChris Mason fs_info->max_extent = (u64)-1; 6621832a6d5SChris Mason fs_info->delalloc_bytes = 0; 663d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 664d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 6652c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 666d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 667d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 668d1310b2eSChris Mason extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree, 6695f39d397SChris Mason fs_info->btree_inode->i_mapping, 6705f39d397SChris Mason GFP_NOFS); 671d1310b2eSChris Mason extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, 672d1310b2eSChris Mason GFP_NOFS); 6730da5468fSChris Mason 674d1310b2eSChris Mason BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; 675d1310b2eSChris Mason 676d1310b2eSChris Mason extent_io_tree_init(&fs_info->free_space_cache, 677f510cfecSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 678d1310b2eSChris Mason extent_io_tree_init(&fs_info->block_group_cache, 67996b5179dSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 680d1310b2eSChris Mason extent_io_tree_init(&fs_info->pinned_extents, 6811a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 682d1310b2eSChris Mason extent_io_tree_init(&fs_info->pending_del, 6831a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 684d1310b2eSChris Mason extent_io_tree_init(&fs_info->extent_ins, 6851a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 686e66f709bSChris Mason fs_info->do_barriers = 1; 687facda1e7SChris Mason fs_info->closing = 0; 688324ae4dfSYan fs_info->total_pinned = 0; 689e18e4809SChris Mason fs_info->last_alloc = 0; 690e18e4809SChris Mason 6916da6abaeSChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 6926da6abaeSChris Mason INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); 6936da6abaeSChris Mason #else 69408607c1bSChris Mason INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 6956da6abaeSChris Mason #endif 6960f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 6970f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 6980f7d52f4SChris Mason sizeof(struct btrfs_key)); 69922b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 700d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 70139279cc3SChris Mason 70279154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 703d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 7043768f368SChris Mason 70519c00ddcSChris Mason #if 0 70619c00ddcSChris Mason ret = add_hasher(fs_info, "crc32c"); 70719c00ddcSChris Mason if (ret) { 70819c00ddcSChris Mason printk("btrfs: failed hash setup, modprobe cryptomgr?\n"); 70919c00ddcSChris Mason err = -ENOMEM; 71019c00ddcSChris Mason goto fail_iput; 71119c00ddcSChris Mason } 71219c00ddcSChris Mason #endif 71387ee04ebSChris Mason __setup_root(512, 512, 512, 512, tree_root, 7142c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 7157eccb903SChris Mason 7162c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 717db94535dSChris Mason BTRFS_SUPER_INFO_OFFSET, 718db94535dSChris Mason 512); 719d98237b3SChris Mason 7200f7d52f4SChris Mason if (!fs_info->sb_buffer) 72139279cc3SChris Mason goto fail_iput; 72239279cc3SChris Mason 7235f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, 7245f39d397SChris Mason sizeof(fs_info->super_copy)); 7255f39d397SChris Mason 7265f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, 7275f39d397SChris Mason (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), 7285f39d397SChris Mason BTRFS_FSID_SIZE); 7295f39d397SChris Mason disk_super = &fs_info->super_copy; 7300f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 73139279cc3SChris Mason goto fail_sb_buffer; 7320f7d52f4SChris Mason 733db94535dSChris Mason nodesize = btrfs_super_nodesize(disk_super); 734db94535dSChris Mason leafsize = btrfs_super_leafsize(disk_super); 735db94535dSChris Mason sectorsize = btrfs_super_sectorsize(disk_super); 73687ee04ebSChris Mason stripesize = btrfs_super_stripesize(disk_super); 737db94535dSChris Mason tree_root->nodesize = nodesize; 738db94535dSChris Mason tree_root->leafsize = leafsize; 739db94535dSChris Mason tree_root->sectorsize = sectorsize; 74087ee04ebSChris Mason tree_root->stripesize = stripesize; 741ff79f819SChris Mason sb_set_blocksize(sb, sectorsize); 742db94535dSChris Mason 7438352d8a4SChris Mason i_size_write(fs_info->btree_inode, 744db94535dSChris Mason btrfs_super_total_bytes(disk_super)); 7458352d8a4SChris Mason 74639279cc3SChris Mason if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 74739279cc3SChris Mason sizeof(disk_super->magic))) { 74839279cc3SChris Mason printk("btrfs: valid FS not found on %s\n", sb->s_id); 74939279cc3SChris Mason goto fail_sb_buffer; 75039279cc3SChris Mason } 75119c00ddcSChris Mason 752db94535dSChris Mason blocksize = btrfs_level_size(tree_root, 753db94535dSChris Mason btrfs_super_root_level(disk_super)); 75419c00ddcSChris Mason 755e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 756db94535dSChris Mason btrfs_super_root(disk_super), 757db94535dSChris Mason blocksize); 75839279cc3SChris Mason if (!tree_root->node) 75939279cc3SChris Mason goto fail_sb_buffer; 7603768f368SChris Mason 7612c90e5d6SChris Mason mutex_lock(&fs_info->fs_mutex); 762db94535dSChris Mason 763db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 764e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 76539279cc3SChris Mason if (ret) { 76639279cc3SChris Mason mutex_unlock(&fs_info->fs_mutex); 76739279cc3SChris Mason goto fail_tree_root; 76839279cc3SChris Mason } 7693768f368SChris Mason 7709078a3e1SChris Mason btrfs_read_block_groups(extent_root); 7719078a3e1SChris Mason 7720f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 7735be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 7740f7d52f4SChris Mason return tree_root; 77539279cc3SChris Mason 77639279cc3SChris Mason fail_tree_root: 7775f39d397SChris Mason free_extent_buffer(tree_root->node); 77839279cc3SChris Mason fail_sb_buffer: 7795f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 78039279cc3SChris Mason fail_iput: 78139279cc3SChris Mason iput(fs_info->btree_inode); 78239279cc3SChris Mason fail: 78339279cc3SChris Mason kfree(extent_root); 78439279cc3SChris Mason kfree(tree_root); 78539279cc3SChris Mason kfree(fs_info); 78639279cc3SChris Mason return ERR_PTR(err); 787eb60ceacSChris Mason } 788eb60ceacSChris Mason 789e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 79079154b1bSChris Mason *root) 791cfaa7295SChris Mason { 792e66f709bSChris Mason int ret; 7935f39d397SChris Mason struct extent_buffer *super = root->fs_info->sb_buffer; 7945f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 79521ad10cfSChris Mason struct super_block *sb = root->fs_info->sb; 7962c90e5d6SChris Mason 79721ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 79821ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 799d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super); 8005f39d397SChris Mason ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, 8015f39d397SChris Mason super->start, super->len); 80221ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 80321ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 8045f39d397SChris Mason return ret; 805cfaa7295SChris Mason } 806cfaa7295SChris Mason 8075eda7b5eSChris Mason int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 8082619ba1fSChris Mason { 8092619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 8102619ba1fSChris Mason (unsigned long)root->root_key.objectid); 811b99aa6cbSChris Mason if (root->in_sysfs) 81258176a96SJosef Bacik btrfs_sysfs_del_root(root); 8132619ba1fSChris Mason if (root->inode) 8142619ba1fSChris Mason iput(root->inode); 8152619ba1fSChris Mason if (root->node) 8165f39d397SChris Mason free_extent_buffer(root->node); 8172619ba1fSChris Mason if (root->commit_root) 8185f39d397SChris Mason free_extent_buffer(root->commit_root); 81958176a96SJosef Bacik if (root->name) 82058176a96SJosef Bacik kfree(root->name); 8212619ba1fSChris Mason kfree(root); 8222619ba1fSChris Mason return 0; 8232619ba1fSChris Mason } 8242619ba1fSChris Mason 82535b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 8260f7d52f4SChris Mason { 8270f7d52f4SChris Mason int ret; 8280f7d52f4SChris Mason struct btrfs_root *gang[8]; 8290f7d52f4SChris Mason int i; 8300f7d52f4SChris Mason 8310f7d52f4SChris Mason while(1) { 8320f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 8330f7d52f4SChris Mason (void **)gang, 0, 8340f7d52f4SChris Mason ARRAY_SIZE(gang)); 8350f7d52f4SChris Mason if (!ret) 8360f7d52f4SChris Mason break; 8372619ba1fSChris Mason for (i = 0; i < ret; i++) 8385eda7b5eSChris Mason btrfs_free_fs_root(fs_info, gang[i]); 8390f7d52f4SChris Mason } 8400f7d52f4SChris Mason return 0; 8410f7d52f4SChris Mason } 842b4100d64SChris Mason 843e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 844eb60ceacSChris Mason { 8453768f368SChris Mason int ret; 846e089f05cSChris Mason struct btrfs_trans_handle *trans; 8470f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 848e089f05cSChris Mason 849facda1e7SChris Mason fs_info->closing = 1; 85008607c1bSChris Mason btrfs_transaction_flush_work(root); 8510f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 8526702ed49SChris Mason btrfs_defrag_dirty_roots(root->fs_info); 85379154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 85454aa1f4dSChris Mason ret = btrfs_commit_transaction(trans, root); 85579154b1bSChris Mason /* run commit again to drop the original snapshot */ 85679154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 85779154b1bSChris Mason btrfs_commit_transaction(trans, root); 85879154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 8599f5fae2fSChris Mason BUG_ON(ret); 86079154b1bSChris Mason write_ctree_super(NULL, root); 8610f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 862ed2ff2cbSChris Mason 8630f7d52f4SChris Mason if (fs_info->extent_root->node) 8645f39d397SChris Mason free_extent_buffer(fs_info->extent_root->node); 865f510cfecSChris Mason 8660f7d52f4SChris Mason if (fs_info->tree_root->node) 8675f39d397SChris Mason free_extent_buffer(fs_info->tree_root->node); 868f510cfecSChris Mason 8695f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 8707eccb903SChris Mason 8719078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 8720f7d52f4SChris Mason del_fs_roots(fs_info); 873d10c5f31SChris Mason 874d10c5f31SChris Mason filemap_write_and_wait(fs_info->btree_inode->i_mapping); 875d10c5f31SChris Mason 876d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->free_space_cache); 877d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->block_group_cache); 878d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pinned_extents); 879d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pending_del); 880d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->extent_ins); 881d1310b2eSChris Mason extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); 882d10c5f31SChris Mason 883db94535dSChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 884d10c5f31SChris Mason 885db94535dSChris Mason iput(fs_info->btree_inode); 88619c00ddcSChris Mason #if 0 88719c00ddcSChris Mason while(!list_empty(&fs_info->hashers)) { 88819c00ddcSChris Mason struct btrfs_hasher *hasher; 88919c00ddcSChris Mason hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher, 89019c00ddcSChris Mason hashers); 89119c00ddcSChris Mason list_del(&hasher->hashers); 89219c00ddcSChris Mason crypto_free_hash(&fs_info->hash_tfm); 89319c00ddcSChris Mason kfree(hasher); 89419c00ddcSChris Mason } 89519c00ddcSChris Mason #endif 8960f7d52f4SChris Mason kfree(fs_info->extent_root); 8970f7d52f4SChris Mason kfree(fs_info->tree_root); 898eb60ceacSChris Mason return 0; 899eb60ceacSChris Mason } 900eb60ceacSChris Mason 9015f39d397SChris Mason int btrfs_buffer_uptodate(struct extent_buffer *buf) 902ccd467d6SChris Mason { 903810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 904d1310b2eSChris Mason return extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); 9055f39d397SChris Mason } 9066702ed49SChris Mason 9075f39d397SChris Mason int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 9085f39d397SChris Mason { 909810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 910d1310b2eSChris Mason return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, 9115f39d397SChris Mason buf); 9125f39d397SChris Mason } 9135f39d397SChris Mason 9145f39d397SChris Mason void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 9155f39d397SChris Mason { 916810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9175f39d397SChris Mason u64 transid = btrfs_header_generation(buf); 9185f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 9196702ed49SChris Mason 920ccd467d6SChris Mason if (transid != root->fs_info->generation) { 921ccd467d6SChris Mason printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 922db94535dSChris Mason (unsigned long long)buf->start, 923ccd467d6SChris Mason transid, root->fs_info->generation); 924ccd467d6SChris Mason WARN_ON(1); 925ccd467d6SChris Mason } 926d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); 927eb60ceacSChris Mason } 928eb60ceacSChris Mason 929e2008b61SChris Mason void btrfs_throttle(struct btrfs_root *root) 930e2008b61SChris Mason { 93155c69072SChris Mason struct backing_dev_info *bdi; 93255c69072SChris Mason 93355c69072SChris Mason bdi = root->fs_info->sb->s_bdev->bd_inode->i_mapping->backing_dev_info; 93404005cc7SChris Mason if (root->fs_info->throttles && bdi_write_congested(bdi)) { 93504005cc7SChris Mason #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) 93655c69072SChris Mason congestion_wait(WRITE, HZ/20); 93704005cc7SChris Mason #else 93804005cc7SChris Mason blk_congestion_wait(WRITE, HZ/20); 93904005cc7SChris Mason #endif 94004005cc7SChris Mason } 941e2008b61SChris Mason } 942e2008b61SChris Mason 943d3c2fdcfSChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) 94435b7e476SChris Mason { 945d3c2fdcfSChris Mason balance_dirty_pages_ratelimited_nr( 946304fced6SChris Mason root->fs_info->btree_inode->i_mapping, 1); 94735b7e476SChris Mason } 9486b80053dSChris Mason 9496b80053dSChris Mason void btrfs_set_buffer_defrag(struct extent_buffer *buf) 9506b80053dSChris Mason { 951810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9526b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 953d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 9546b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 9556b80053dSChris Mason } 9566b80053dSChris Mason 9576b80053dSChris Mason void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 9586b80053dSChris Mason { 959810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9606b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 961d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 9626b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 9636b80053dSChris Mason GFP_NOFS); 9646b80053dSChris Mason } 9656b80053dSChris Mason 9666b80053dSChris Mason int btrfs_buffer_defrag(struct extent_buffer *buf) 9676b80053dSChris Mason { 968810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9696b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 970d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 9716b80053dSChris Mason buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 9726b80053dSChris Mason } 9736b80053dSChris Mason 9746b80053dSChris Mason int btrfs_buffer_defrag_done(struct extent_buffer *buf) 9756b80053dSChris Mason { 976810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9776b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 978d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 9796b80053dSChris Mason buf->start, buf->start + buf->len - 1, 9806b80053dSChris Mason EXTENT_DEFRAG_DONE, 0); 9816b80053dSChris Mason } 9826b80053dSChris Mason 9836b80053dSChris Mason int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 9846b80053dSChris Mason { 985810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9866b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 987d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 9886b80053dSChris Mason buf->start, buf->start + buf->len - 1, 9896b80053dSChris Mason EXTENT_DEFRAG_DONE, GFP_NOFS); 9906b80053dSChris Mason } 9916b80053dSChris Mason 9926b80053dSChris Mason int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 9936b80053dSChris Mason { 994810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9956b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 996d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 9976b80053dSChris Mason buf->start, buf->start + buf->len - 1, 9986b80053dSChris Mason EXTENT_DEFRAG, GFP_NOFS); 9996b80053dSChris Mason } 10006b80053dSChris Mason 10016b80053dSChris Mason int btrfs_read_buffer(struct extent_buffer *buf) 10026b80053dSChris Mason { 1003810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10046b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1005d1310b2eSChris Mason return read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 100619c00ddcSChris Mason buf, 0, 1); 10076b80053dSChris Mason } 10080da5468fSChris Mason 1009d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops = { 10100da5468fSChris Mason .writepage_io_hook = btree_writepage_io_hook, 10110da5468fSChris Mason }; 1012