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 460da5468fSChris Mason static struct extent_map_ops btree_extent_map_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; 53f510cfecSChris Mason eb = find_extent_buffer(&BTRFS_I(btree_inode)->extent_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 64f510cfecSChris Mason eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_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, 705f39d397SChris Mason size_t page_offset, u64 start, u64 end, 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: 785f39d397SChris Mason em = lookup_extent_mapping(em_tree, start, end); 795f39d397SChris Mason if (em) { 805f39d397SChris Mason goto out; 815f39d397SChris Mason } 825f39d397SChris Mason em = alloc_extent_map(GFP_NOFS); 835f39d397SChris Mason if (!em) { 845f39d397SChris Mason em = ERR_PTR(-ENOMEM); 855f39d397SChris Mason goto out; 865f39d397SChris Mason } 875f39d397SChris Mason em->start = 0; 885f39d397SChris Mason em->end = (i_size_read(inode) & ~((u64)PAGE_CACHE_SIZE -1)) - 1; 895f39d397SChris Mason em->block_start = 0; 905f39d397SChris Mason em->block_end = em->end; 915f39d397SChris Mason em->bdev = inode->i_sb->s_bdev; 925f39d397SChris Mason ret = add_extent_mapping(em_tree, em); 935f39d397SChris Mason if (ret == -EEXIST) { 945f39d397SChris Mason free_extent_map(em); 955f39d397SChris Mason em = NULL; 965f39d397SChris Mason goto again; 975f39d397SChris Mason } else if (ret) { 985f39d397SChris Mason em = ERR_PTR(ret); 995f39d397SChris Mason } 1005f39d397SChris Mason out: 1015f39d397SChris Mason return em; 1025f39d397SChris Mason } 1035f39d397SChris Mason 10419c00ddcSChris Mason u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 10519c00ddcSChris Mason { 10619c00ddcSChris Mason return crc32c(seed, data, len); 10719c00ddcSChris Mason } 10819c00ddcSChris Mason 10919c00ddcSChris Mason void btrfs_csum_final(u32 crc, char *result) 11019c00ddcSChris Mason { 11119c00ddcSChris Mason *(__le32 *)result = ~cpu_to_le32(crc); 11219c00ddcSChris Mason } 11319c00ddcSChris Mason 11419c00ddcSChris Mason static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 11519c00ddcSChris Mason int verify) 11619c00ddcSChris Mason { 11719c00ddcSChris Mason char result[BTRFS_CRC32_SIZE]; 11819c00ddcSChris Mason unsigned long len; 11919c00ddcSChris Mason unsigned long cur_len; 12019c00ddcSChris Mason unsigned long offset = BTRFS_CSUM_SIZE; 12119c00ddcSChris Mason char *map_token = NULL; 12219c00ddcSChris Mason char *kaddr; 12319c00ddcSChris Mason unsigned long map_start; 12419c00ddcSChris Mason unsigned long map_len; 12519c00ddcSChris Mason int err; 12619c00ddcSChris Mason u32 crc = ~(u32)0; 12719c00ddcSChris Mason 12819c00ddcSChris Mason len = buf->len - offset; 12919c00ddcSChris Mason while(len > 0) { 13019c00ddcSChris Mason err = map_private_extent_buffer(buf, offset, 32, 13119c00ddcSChris Mason &map_token, &kaddr, 13219c00ddcSChris Mason &map_start, &map_len, KM_USER0); 13319c00ddcSChris Mason if (err) { 13419c00ddcSChris Mason printk("failed to map extent buffer! %lu\n", 13519c00ddcSChris Mason offset); 13619c00ddcSChris Mason return 1; 13719c00ddcSChris Mason } 13819c00ddcSChris Mason cur_len = min(len, map_len - (offset - map_start)); 13919c00ddcSChris Mason crc = btrfs_csum_data(root, kaddr + offset - map_start, 14019c00ddcSChris Mason crc, cur_len); 14119c00ddcSChris Mason len -= cur_len; 14219c00ddcSChris Mason offset += cur_len; 14319c00ddcSChris Mason unmap_extent_buffer(buf, map_token, KM_USER0); 14419c00ddcSChris Mason } 14519c00ddcSChris Mason btrfs_csum_final(crc, result); 14619c00ddcSChris Mason 14719c00ddcSChris Mason if (verify) { 14819c00ddcSChris Mason if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 14919c00ddcSChris Mason printk("btrfs: %s checksum verify failed on %llu\n", 15019c00ddcSChris Mason root->fs_info->sb->s_id, 15119c00ddcSChris Mason buf->start); 15219c00ddcSChris Mason return 1; 15319c00ddcSChris Mason } 15419c00ddcSChris Mason } else { 15519c00ddcSChris Mason write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 15619c00ddcSChris Mason } 15719c00ddcSChris Mason return 0; 15819c00ddcSChris Mason } 15919c00ddcSChris Mason 16019c00ddcSChris Mason 16119c00ddcSChris Mason int csum_dirty_buffer(struct btrfs_root *root, struct page *page) 16219c00ddcSChris Mason { 16319c00ddcSChris Mason struct extent_map_tree *tree; 16435ebb934SChris Mason u64 start = (u64)page->index << PAGE_CACHE_SHIFT; 16519c00ddcSChris Mason u64 found_start; 16619c00ddcSChris Mason int found_level; 16719c00ddcSChris Mason unsigned long len; 16819c00ddcSChris Mason struct extent_buffer *eb; 16919c00ddcSChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 17019c00ddcSChris Mason 17119c00ddcSChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 17219c00ddcSChris Mason goto out; 17319c00ddcSChris Mason if (!page->private) 17419c00ddcSChris Mason goto out; 17519c00ddcSChris Mason len = page->private >> 2; 17619c00ddcSChris Mason if (len == 0) { 17719c00ddcSChris Mason WARN_ON(1); 17819c00ddcSChris Mason } 17919c00ddcSChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 18019c00ddcSChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1); 18119c00ddcSChris Mason found_start = btrfs_header_bytenr(eb); 18219c00ddcSChris Mason if (found_start != start) { 18319c00ddcSChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 18419c00ddcSChris Mason start, found_start, len); 18519c00ddcSChris Mason } 18619c00ddcSChris Mason found_level = btrfs_header_level(eb); 18719c00ddcSChris Mason csum_tree_block(root, eb, 0); 18819c00ddcSChris Mason free_extent_buffer(eb); 18919c00ddcSChris Mason out: 19019c00ddcSChris Mason return 0; 19119c00ddcSChris Mason } 19219c00ddcSChris Mason 1930da5468fSChris Mason static int btree_writepage_io_hook(struct page *page, u64 start, u64 end) 1940da5468fSChris Mason { 1950da5468fSChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 1960da5468fSChris Mason 1970da5468fSChris Mason csum_dirty_buffer(root, page); 1980da5468fSChris Mason return 0; 1990da5468fSChris Mason } 2000da5468fSChris Mason 2015f39d397SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 2025f39d397SChris Mason { 2035f39d397SChris Mason struct extent_map_tree *tree; 2045f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2055f39d397SChris Mason return extent_write_full_page(tree, page, btree_get_extent, wbc); 2065f39d397SChris Mason } 2070da5468fSChris Mason 2080da5468fSChris Mason static int btree_writepages(struct address_space *mapping, 2090da5468fSChris Mason struct writeback_control *wbc) 2100da5468fSChris Mason { 2110da5468fSChris Mason struct extent_map_tree *tree; 2120da5468fSChris Mason tree = &BTRFS_I(mapping->host)->extent_tree; 213d8d5f3e1SChris Mason if (wbc->sync_mode == WB_SYNC_NONE) { 214793955bcSChris Mason u64 num_dirty; 215793955bcSChris Mason u64 start = 0; 216793955bcSChris Mason unsigned long thresh = 96 * 1024 * 1024; 217448d640bSChris Mason 218448d640bSChris Mason if (wbc->for_kupdate) 219448d640bSChris Mason return 0; 220448d640bSChris Mason 221ca664626SChris Mason if (current_is_pdflush()) { 222ca664626SChris Mason thresh = 96 * 1024 * 1024; 223ca664626SChris Mason } else { 224ca664626SChris Mason thresh = 8 * 1024 * 1024; 225ca664626SChris Mason } 2261832a6d5SChris Mason num_dirty = count_range_bits(tree, &start, (u64)-1, 2271832a6d5SChris Mason thresh, EXTENT_DIRTY); 228793955bcSChris Mason if (num_dirty < thresh) { 229793955bcSChris Mason return 0; 230793955bcSChris Mason } 231793955bcSChris Mason } 2320da5468fSChris Mason return extent_writepages(tree, mapping, btree_get_extent, wbc); 2330da5468fSChris Mason } 2340da5468fSChris Mason 2355f39d397SChris Mason int btree_readpage(struct file *file, struct page *page) 2365f39d397SChris Mason { 2375f39d397SChris Mason struct extent_map_tree *tree; 2385f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2395f39d397SChris Mason return extent_read_full_page(tree, page, btree_get_extent); 2405f39d397SChris Mason } 2415f39d397SChris Mason 2425f39d397SChris Mason static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags) 2435f39d397SChris Mason { 2445f39d397SChris Mason struct extent_map_tree *tree; 2455f39d397SChris Mason int ret; 2465f39d397SChris Mason 2475f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2485f39d397SChris Mason ret = try_release_extent_mapping(tree, page); 2495f39d397SChris Mason if (ret == 1) { 2505f39d397SChris Mason ClearPagePrivate(page); 2515f39d397SChris Mason set_page_private(page, 0); 252d98237b3SChris Mason page_cache_release(page); 2535f39d397SChris Mason } 254d98237b3SChris Mason return ret; 255d98237b3SChris Mason } 256d98237b3SChris Mason 2575f39d397SChris Mason static void btree_invalidatepage(struct page *page, unsigned long offset) 258d98237b3SChris Mason { 2595f39d397SChris Mason struct extent_map_tree *tree; 2605f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2615f39d397SChris Mason extent_invalidatepage(tree, page, offset); 2625f39d397SChris Mason btree_releasepage(page, GFP_NOFS); 263d98237b3SChris Mason } 264d98237b3SChris Mason 2655f39d397SChris Mason #if 0 266d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 267d98237b3SChris Mason { 26887cbda5cSChris Mason struct buffer_head *bh; 2690f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 27087cbda5cSChris Mason struct buffer_head *head; 27187cbda5cSChris Mason if (!page_has_buffers(page)) { 27287cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 27387cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 27487cbda5cSChris Mason } 27587cbda5cSChris Mason head = page_buffers(page); 27687cbda5cSChris Mason bh = head; 27787cbda5cSChris Mason do { 27887cbda5cSChris Mason if (buffer_dirty(bh)) 27987cbda5cSChris Mason csum_tree_block(root, bh, 0); 28087cbda5cSChris Mason bh = bh->b_this_page; 28187cbda5cSChris Mason } while (bh != head); 282d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 283d98237b3SChris Mason } 2845f39d397SChris Mason #endif 285d98237b3SChris Mason 286d98237b3SChris Mason static struct address_space_operations btree_aops = { 287d98237b3SChris Mason .readpage = btree_readpage, 288d98237b3SChris Mason .writepage = btree_writepage, 2890da5468fSChris Mason .writepages = btree_writepages, 2905f39d397SChris Mason .releasepage = btree_releasepage, 2915f39d397SChris Mason .invalidatepage = btree_invalidatepage, 292d98237b3SChris Mason .sync_page = block_sync_page, 293d98237b3SChris Mason }; 294123abc88SChris Mason 295db94535dSChris Mason int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) 296090d1875SChris Mason { 2975f39d397SChris Mason struct extent_buffer *buf = NULL; 2985f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 299de428b63SChris Mason int ret = 0; 300090d1875SChris Mason 301db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3025f39d397SChris Mason if (!buf) 303090d1875SChris Mason return 0; 3045f39d397SChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 30519c00ddcSChris Mason buf, 0, 0); 3065f39d397SChris Mason free_extent_buffer(buf); 307de428b63SChris Mason return ret; 308090d1875SChris Mason } 309090d1875SChris Mason 310db94535dSChris Mason struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 311db94535dSChris Mason u32 blocksize) 312e20d96d6SChris Mason { 3135f39d397SChris Mason struct extent_buffer *buf = NULL; 3145f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 31519c00ddcSChris Mason struct extent_map_tree *extent_tree; 31619c00ddcSChris Mason int ret; 31719c00ddcSChris Mason 31819c00ddcSChris Mason extent_tree = &BTRFS_I(btree_inode)->extent_tree; 319e20d96d6SChris Mason 320db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3215f39d397SChris Mason if (!buf) 322d98237b3SChris Mason return NULL; 3235f39d397SChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 32419c00ddcSChris Mason buf, 0, 1); 32519c00ddcSChris Mason if (buf->flags & EXTENT_CSUM) { 32619c00ddcSChris Mason return buf; 32719c00ddcSChris Mason } 32819c00ddcSChris Mason if (test_range_bit(extent_tree, buf->start, buf->start + buf->len - 1, 32919c00ddcSChris Mason EXTENT_CSUM, 1)) { 33019c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 33119c00ddcSChris Mason return buf; 33219c00ddcSChris Mason } 33319c00ddcSChris Mason ret = csum_tree_block(root, buf, 1); 33419c00ddcSChris Mason set_extent_bits(extent_tree, buf->start, 33519c00ddcSChris Mason buf->start + buf->len - 1, 33619c00ddcSChris Mason EXTENT_CSUM, GFP_NOFS); 33719c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 3385f39d397SChris Mason return buf; 339eb60ceacSChris Mason } 340eb60ceacSChris Mason 341e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 3425f39d397SChris Mason struct extent_buffer *buf) 343ed2ff2cbSChris Mason { 3445f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 3455f39d397SChris Mason clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); 3465f39d397SChris Mason return 0; 3475f39d397SChris Mason } 3485f39d397SChris Mason 3495f39d397SChris Mason int wait_on_tree_block_writeback(struct btrfs_root *root, 3505f39d397SChris Mason struct extent_buffer *buf) 3515f39d397SChris Mason { 3525f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 3535f39d397SChris Mason wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->extent_tree, 3545f39d397SChris Mason buf); 3555f39d397SChris Mason return 0; 3565f39d397SChris Mason } 3575f39d397SChris Mason 358db94535dSChris Mason static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 35987ee04ebSChris Mason u32 stripesize, struct btrfs_root *root, 3609f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 361e20d96d6SChris Mason u64 objectid) 362d97e63b6SChris Mason { 363cfaa7295SChris Mason root->node = NULL; 3640f7d52f4SChris Mason root->inode = NULL; 365a28ec197SChris Mason root->commit_root = NULL; 366db94535dSChris Mason root->sectorsize = sectorsize; 367db94535dSChris Mason root->nodesize = nodesize; 368db94535dSChris Mason root->leafsize = leafsize; 36987ee04ebSChris Mason root->stripesize = stripesize; 370123abc88SChris Mason root->ref_cows = 0; 3719f5fae2fSChris Mason root->fs_info = fs_info; 3720f7d52f4SChris Mason root->objectid = objectid; 3730f7d52f4SChris Mason root->last_trans = 0; 3741b05da2eSChris Mason root->highest_inode = 0; 3751b05da2eSChris Mason root->last_inode_alloc = 0; 37658176a96SJosef Bacik root->name = NULL; 3773768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 3783768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 3796702ed49SChris Mason memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 38058176a96SJosef Bacik memset(&root->root_kobj, 0, sizeof(root->root_kobj)); 38158176a96SJosef Bacik init_completion(&root->kobj_unregister); 382011410bdSChris Mason init_rwsem(&root->snap_sem); 3836702ed49SChris Mason root->defrag_running = 0; 3846702ed49SChris Mason root->defrag_level = 0; 3854d775673SChris Mason root->root_key.objectid = objectid; 3863768f368SChris Mason return 0; 3873768f368SChris Mason } 3883768f368SChris Mason 389db94535dSChris Mason static int find_and_setup_root(struct btrfs_root *tree_root, 3909f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 3919f5fae2fSChris Mason u64 objectid, 392e20d96d6SChris Mason struct btrfs_root *root) 3933768f368SChris Mason { 3943768f368SChris Mason int ret; 395db94535dSChris Mason u32 blocksize; 3963768f368SChris Mason 397db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 39887ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 39987ee04ebSChris Mason root, fs_info, objectid); 4003768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 4013768f368SChris Mason &root->root_item, &root->root_key); 4023768f368SChris Mason BUG_ON(ret); 4033768f368SChris Mason 404db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 405db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 406db94535dSChris Mason blocksize); 4073768f368SChris Mason BUG_ON(!root->node); 408d97e63b6SChris Mason return 0; 409d97e63b6SChris Mason } 410d97e63b6SChris Mason 4115eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 4120f7d52f4SChris Mason struct btrfs_key *location) 4130f7d52f4SChris Mason { 4140f7d52f4SChris Mason struct btrfs_root *root; 4150f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 4160f7d52f4SChris Mason struct btrfs_path *path; 4175f39d397SChris Mason struct extent_buffer *l; 4181b05da2eSChris Mason u64 highest_inode; 419db94535dSChris Mason u32 blocksize; 4200f7d52f4SChris Mason int ret = 0; 4210f7d52f4SChris Mason 4225eda7b5eSChris Mason root = kzalloc(sizeof(*root), GFP_NOFS); 4230cf6c620SChris Mason if (!root) 4240f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 4250f7d52f4SChris Mason if (location->offset == (u64)-1) { 426db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 4270f7d52f4SChris Mason location->objectid, root); 4280f7d52f4SChris Mason if (ret) { 4290f7d52f4SChris Mason kfree(root); 4300f7d52f4SChris Mason return ERR_PTR(ret); 4310f7d52f4SChris Mason } 4320f7d52f4SChris Mason goto insert; 4330f7d52f4SChris Mason } 4340f7d52f4SChris Mason 435db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 43687ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 43787ee04ebSChris Mason root, fs_info, location->objectid); 4380f7d52f4SChris Mason 4390f7d52f4SChris Mason path = btrfs_alloc_path(); 4400f7d52f4SChris Mason BUG_ON(!path); 4410f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 4420f7d52f4SChris Mason if (ret != 0) { 4430f7d52f4SChris Mason if (ret > 0) 4440f7d52f4SChris Mason ret = -ENOENT; 4450f7d52f4SChris Mason goto out; 4460f7d52f4SChris Mason } 4475f39d397SChris Mason l = path->nodes[0]; 4485f39d397SChris Mason read_extent_buffer(l, &root->root_item, 4495f39d397SChris Mason btrfs_item_ptr_offset(l, path->slots[0]), 4500f7d52f4SChris Mason sizeof(root->root_item)); 45144b36eb2SYan Zheng memcpy(&root->root_key, location, sizeof(*location)); 4520f7d52f4SChris Mason ret = 0; 4530f7d52f4SChris Mason out: 4540f7d52f4SChris Mason btrfs_release_path(root, path); 4550f7d52f4SChris Mason btrfs_free_path(path); 4560f7d52f4SChris Mason if (ret) { 4570f7d52f4SChris Mason kfree(root); 4580f7d52f4SChris Mason return ERR_PTR(ret); 4590f7d52f4SChris Mason } 460db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 461db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 462db94535dSChris Mason blocksize); 4630f7d52f4SChris Mason BUG_ON(!root->node); 4640f7d52f4SChris Mason insert: 4650f7d52f4SChris Mason root->ref_cows = 1; 4665eda7b5eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 4675eda7b5eSChris Mason if (ret == 0) { 4685eda7b5eSChris Mason root->highest_inode = highest_inode; 4695eda7b5eSChris Mason root->last_inode_alloc = highest_inode; 4705eda7b5eSChris Mason } 4715eda7b5eSChris Mason return root; 4725eda7b5eSChris Mason } 4735eda7b5eSChris Mason 474edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, 475edbd8d4eSChris Mason struct btrfs_key *location) 4765eda7b5eSChris Mason { 4775eda7b5eSChris Mason struct btrfs_root *root; 4785eda7b5eSChris Mason int ret; 4795eda7b5eSChris Mason 480edbd8d4eSChris Mason if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) 481edbd8d4eSChris Mason return fs_info->tree_root; 482edbd8d4eSChris Mason if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) 483edbd8d4eSChris Mason return fs_info->extent_root; 484edbd8d4eSChris Mason 4855eda7b5eSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 4865eda7b5eSChris Mason (unsigned long)location->objectid); 4875eda7b5eSChris Mason if (root) 4885eda7b5eSChris Mason return root; 4895eda7b5eSChris Mason 4905eda7b5eSChris Mason root = btrfs_read_fs_root_no_radix(fs_info, location); 4915eda7b5eSChris Mason if (IS_ERR(root)) 4925eda7b5eSChris Mason return root; 4932619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 4942619ba1fSChris Mason (unsigned long)root->root_key.objectid, 4950f7d52f4SChris Mason root); 4960f7d52f4SChris Mason if (ret) { 4975f39d397SChris Mason free_extent_buffer(root->node); 4980f7d52f4SChris Mason kfree(root); 4990f7d52f4SChris Mason return ERR_PTR(ret); 5000f7d52f4SChris Mason } 501edbd8d4eSChris Mason ret = btrfs_find_dead_roots(fs_info->tree_root, 502edbd8d4eSChris Mason root->root_key.objectid, root); 503edbd8d4eSChris Mason BUG_ON(ret); 504edbd8d4eSChris Mason 505edbd8d4eSChris Mason return root; 506edbd8d4eSChris Mason } 507edbd8d4eSChris Mason 508edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 509edbd8d4eSChris Mason struct btrfs_key *location, 510edbd8d4eSChris Mason const char *name, int namelen) 511edbd8d4eSChris Mason { 512edbd8d4eSChris Mason struct btrfs_root *root; 513edbd8d4eSChris Mason int ret; 514edbd8d4eSChris Mason 515edbd8d4eSChris Mason root = btrfs_read_fs_root_no_name(fs_info, location); 516edbd8d4eSChris Mason if (!root) 517edbd8d4eSChris Mason return NULL; 51858176a96SJosef Bacik 51958176a96SJosef Bacik ret = btrfs_set_root_name(root, name, namelen); 52058176a96SJosef Bacik if (ret) { 5215f39d397SChris Mason free_extent_buffer(root->node); 52258176a96SJosef Bacik kfree(root); 52358176a96SJosef Bacik return ERR_PTR(ret); 52458176a96SJosef Bacik } 52558176a96SJosef Bacik 52658176a96SJosef Bacik ret = btrfs_sysfs_add_root(root); 52758176a96SJosef Bacik if (ret) { 5285f39d397SChris Mason free_extent_buffer(root->node); 52958176a96SJosef Bacik kfree(root->name); 53058176a96SJosef Bacik kfree(root); 53158176a96SJosef Bacik return ERR_PTR(ret); 53258176a96SJosef Bacik } 5330f7d52f4SChris Mason return root; 5340f7d52f4SChris Mason } 53519c00ddcSChris Mason #if 0 53619c00ddcSChris Mason static int add_hasher(struct btrfs_fs_info *info, char *type) { 53719c00ddcSChris Mason struct btrfs_hasher *hasher; 5380f7d52f4SChris Mason 53919c00ddcSChris Mason hasher = kmalloc(sizeof(*hasher), GFP_NOFS); 54019c00ddcSChris Mason if (!hasher) 54119c00ddcSChris Mason return -ENOMEM; 54219c00ddcSChris Mason hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC); 54319c00ddcSChris Mason if (!hasher->hash_tfm) { 54419c00ddcSChris Mason kfree(hasher); 54519c00ddcSChris Mason return -EINVAL; 54619c00ddcSChris Mason } 54719c00ddcSChris Mason spin_lock(&info->hash_lock); 54819c00ddcSChris Mason list_add(&hasher->list, &info->hashers); 54919c00ddcSChris Mason spin_unlock(&info->hash_lock); 55019c00ddcSChris Mason return 0; 55119c00ddcSChris Mason } 55219c00ddcSChris Mason #endif 5532c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 554eb60ceacSChris Mason { 555db94535dSChris Mason u32 sectorsize; 556db94535dSChris Mason u32 nodesize; 557db94535dSChris Mason u32 leafsize; 558db94535dSChris Mason u32 blocksize; 55987ee04ebSChris Mason u32 stripesize; 560e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 561e20d96d6SChris Mason GFP_NOFS); 562e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 563e20d96d6SChris Mason GFP_NOFS); 564e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 565e20d96d6SChris Mason GFP_NOFS); 566eb60ceacSChris Mason int ret; 56739279cc3SChris Mason int err = -EIO; 5682c90e5d6SChris Mason struct btrfs_super_block *disk_super; 569eb60ceacSChris Mason 57039279cc3SChris Mason if (!extent_root || !tree_root || !fs_info) { 57139279cc3SChris Mason err = -ENOMEM; 57239279cc3SChris Mason goto fail; 57339279cc3SChris Mason } 5740f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 5758fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 576facda1e7SChris Mason INIT_LIST_HEAD(&fs_info->dead_roots); 57719c00ddcSChris Mason INIT_LIST_HEAD(&fs_info->hashers); 57819c00ddcSChris Mason spin_lock_init(&fs_info->hash_lock); 5791832a6d5SChris Mason spin_lock_init(&fs_info->delalloc_lock); 58019c00ddcSChris Mason 58158176a96SJosef Bacik memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj)); 58258176a96SJosef Bacik init_completion(&fs_info->kobj_unregister); 5832c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 5849f5fae2fSChris Mason fs_info->running_transaction = NULL; 58515ee9bc7SJosef Bacik fs_info->last_trans_committed = 0; 5869f5fae2fSChris Mason fs_info->tree_root = tree_root; 5879f5fae2fSChris Mason fs_info->extent_root = extent_root; 588e20d96d6SChris Mason fs_info->sb = sb; 589b6cda9bcSChris Mason fs_info->mount_opt = 0; 590c59f8951SChris Mason fs_info->max_extent = (u64)-1; 5911832a6d5SChris Mason fs_info->delalloc_bytes = 0; 592d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 593d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 5942c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 595d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 596d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 5975f39d397SChris Mason extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, 5985f39d397SChris Mason fs_info->btree_inode->i_mapping, 5995f39d397SChris Mason GFP_NOFS); 6000da5468fSChris Mason BTRFS_I(fs_info->btree_inode)->extent_tree.ops = &btree_extent_map_ops; 6010da5468fSChris Mason 602f510cfecSChris Mason extent_map_tree_init(&fs_info->free_space_cache, 603f510cfecSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 60496b5179dSChris Mason extent_map_tree_init(&fs_info->block_group_cache, 60596b5179dSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 6061a5bc167SChris Mason extent_map_tree_init(&fs_info->pinned_extents, 6071a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 6081a5bc167SChris Mason extent_map_tree_init(&fs_info->pending_del, 6091a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 6101a5bc167SChris Mason extent_map_tree_init(&fs_info->extent_ins, 6111a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 612e66f709bSChris Mason fs_info->do_barriers = 1; 613facda1e7SChris Mason fs_info->closing = 0; 614324ae4dfSYan fs_info->total_pinned = 0; 6156da6abaeSChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 6166da6abaeSChris Mason INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); 6176da6abaeSChris Mason #else 61808607c1bSChris Mason INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 6196da6abaeSChris Mason #endif 6200f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 6210f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 6220f7d52f4SChris Mason sizeof(struct btrfs_key)); 62322b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 624d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 62539279cc3SChris Mason 62679154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 627d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 6283768f368SChris Mason 62919c00ddcSChris Mason #if 0 63019c00ddcSChris Mason ret = add_hasher(fs_info, "crc32c"); 63119c00ddcSChris Mason if (ret) { 63219c00ddcSChris Mason printk("btrfs: failed hash setup, modprobe cryptomgr?\n"); 63319c00ddcSChris Mason err = -ENOMEM; 63419c00ddcSChris Mason goto fail_iput; 63519c00ddcSChris Mason } 63619c00ddcSChris Mason #endif 63787ee04ebSChris Mason __setup_root(512, 512, 512, 512, tree_root, 6382c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 6397eccb903SChris Mason 6402c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 641db94535dSChris Mason BTRFS_SUPER_INFO_OFFSET, 642db94535dSChris Mason 512); 643d98237b3SChris Mason 6440f7d52f4SChris Mason if (!fs_info->sb_buffer) 64539279cc3SChris Mason goto fail_iput; 64639279cc3SChris Mason 6475f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, 6485f39d397SChris Mason sizeof(fs_info->super_copy)); 6495f39d397SChris Mason 6505f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, 6515f39d397SChris Mason (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), 6525f39d397SChris Mason BTRFS_FSID_SIZE); 6535f39d397SChris Mason disk_super = &fs_info->super_copy; 6540f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 65539279cc3SChris Mason goto fail_sb_buffer; 6560f7d52f4SChris Mason 657db94535dSChris Mason nodesize = btrfs_super_nodesize(disk_super); 658db94535dSChris Mason leafsize = btrfs_super_leafsize(disk_super); 659db94535dSChris Mason sectorsize = btrfs_super_sectorsize(disk_super); 66087ee04ebSChris Mason stripesize = btrfs_super_stripesize(disk_super); 661db94535dSChris Mason tree_root->nodesize = nodesize; 662db94535dSChris Mason tree_root->leafsize = leafsize; 663db94535dSChris Mason tree_root->sectorsize = sectorsize; 66487ee04ebSChris Mason tree_root->stripesize = stripesize; 665ff79f819SChris Mason sb_set_blocksize(sb, sectorsize); 666db94535dSChris Mason 6678352d8a4SChris Mason i_size_write(fs_info->btree_inode, 668db94535dSChris Mason btrfs_super_total_bytes(disk_super)); 6698352d8a4SChris Mason 67039279cc3SChris Mason if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 67139279cc3SChris Mason sizeof(disk_super->magic))) { 67239279cc3SChris Mason printk("btrfs: valid FS not found on %s\n", sb->s_id); 67339279cc3SChris Mason goto fail_sb_buffer; 67439279cc3SChris Mason } 67519c00ddcSChris Mason 676db94535dSChris Mason blocksize = btrfs_level_size(tree_root, 677db94535dSChris Mason btrfs_super_root_level(disk_super)); 67819c00ddcSChris Mason 679e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 680db94535dSChris Mason btrfs_super_root(disk_super), 681db94535dSChris Mason blocksize); 68239279cc3SChris Mason if (!tree_root->node) 68339279cc3SChris Mason goto fail_sb_buffer; 6843768f368SChris Mason 6852c90e5d6SChris Mason mutex_lock(&fs_info->fs_mutex); 686db94535dSChris Mason 687db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 688e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 68939279cc3SChris Mason if (ret) { 69039279cc3SChris Mason mutex_unlock(&fs_info->fs_mutex); 69139279cc3SChris Mason goto fail_tree_root; 69239279cc3SChris Mason } 6933768f368SChris Mason 6949078a3e1SChris Mason btrfs_read_block_groups(extent_root); 6959078a3e1SChris Mason 6960f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 6975be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 6980f7d52f4SChris Mason return tree_root; 69939279cc3SChris Mason 70039279cc3SChris Mason fail_tree_root: 7015f39d397SChris Mason free_extent_buffer(tree_root->node); 70239279cc3SChris Mason fail_sb_buffer: 7035f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 70439279cc3SChris Mason fail_iput: 70539279cc3SChris Mason iput(fs_info->btree_inode); 70639279cc3SChris Mason fail: 70739279cc3SChris Mason kfree(extent_root); 70839279cc3SChris Mason kfree(tree_root); 70939279cc3SChris Mason kfree(fs_info); 71039279cc3SChris Mason return ERR_PTR(err); 711eb60ceacSChris Mason } 712eb60ceacSChris Mason 713e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 71479154b1bSChris Mason *root) 715cfaa7295SChris Mason { 716e66f709bSChris Mason int ret; 7175f39d397SChris Mason struct extent_buffer *super = root->fs_info->sb_buffer; 7185f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 7192c90e5d6SChris Mason 7205f39d397SChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, super); 7215f39d397SChris Mason ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, 7225f39d397SChris Mason super->start, super->len); 7235f39d397SChris Mason return ret; 724cfaa7295SChris Mason } 725cfaa7295SChris Mason 7265eda7b5eSChris Mason int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 7272619ba1fSChris Mason { 7282619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 7292619ba1fSChris Mason (unsigned long)root->root_key.objectid); 73058176a96SJosef Bacik btrfs_sysfs_del_root(root); 7312619ba1fSChris Mason if (root->inode) 7322619ba1fSChris Mason iput(root->inode); 7332619ba1fSChris Mason if (root->node) 7345f39d397SChris Mason free_extent_buffer(root->node); 7352619ba1fSChris Mason if (root->commit_root) 7365f39d397SChris Mason free_extent_buffer(root->commit_root); 73758176a96SJosef Bacik if (root->name) 73858176a96SJosef Bacik kfree(root->name); 7392619ba1fSChris Mason kfree(root); 7402619ba1fSChris Mason return 0; 7412619ba1fSChris Mason } 7422619ba1fSChris Mason 74335b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 7440f7d52f4SChris Mason { 7450f7d52f4SChris Mason int ret; 7460f7d52f4SChris Mason struct btrfs_root *gang[8]; 7470f7d52f4SChris Mason int i; 7480f7d52f4SChris Mason 7490f7d52f4SChris Mason while(1) { 7500f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 7510f7d52f4SChris Mason (void **)gang, 0, 7520f7d52f4SChris Mason ARRAY_SIZE(gang)); 7530f7d52f4SChris Mason if (!ret) 7540f7d52f4SChris Mason break; 7552619ba1fSChris Mason for (i = 0; i < ret; i++) 7565eda7b5eSChris Mason btrfs_free_fs_root(fs_info, gang[i]); 7570f7d52f4SChris Mason } 7580f7d52f4SChris Mason return 0; 7590f7d52f4SChris Mason } 760b4100d64SChris Mason 761e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 762eb60ceacSChris Mason { 7633768f368SChris Mason int ret; 764e089f05cSChris Mason struct btrfs_trans_handle *trans; 7650f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 766e089f05cSChris Mason 767facda1e7SChris Mason fs_info->closing = 1; 76808607c1bSChris Mason btrfs_transaction_flush_work(root); 7690f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 7706702ed49SChris Mason btrfs_defrag_dirty_roots(root->fs_info); 77179154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 77254aa1f4dSChris Mason ret = btrfs_commit_transaction(trans, root); 77379154b1bSChris Mason /* run commit again to drop the original snapshot */ 77479154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 77579154b1bSChris Mason btrfs_commit_transaction(trans, root); 77679154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 7779f5fae2fSChris Mason BUG_ON(ret); 77879154b1bSChris Mason write_ctree_super(NULL, root); 7790f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 780ed2ff2cbSChris Mason 7810f7d52f4SChris Mason if (fs_info->extent_root->node) 7825f39d397SChris Mason free_extent_buffer(fs_info->extent_root->node); 783f510cfecSChris Mason 7840f7d52f4SChris Mason if (fs_info->tree_root->node) 7855f39d397SChris Mason free_extent_buffer(fs_info->tree_root->node); 786f510cfecSChris Mason 7875f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 7887eccb903SChris Mason 7899078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 7900f7d52f4SChris Mason del_fs_roots(fs_info); 791d10c5f31SChris Mason 792d10c5f31SChris Mason filemap_write_and_wait(fs_info->btree_inode->i_mapping); 793d10c5f31SChris Mason 794d10c5f31SChris Mason extent_map_tree_empty_lru(&fs_info->free_space_cache); 795d10c5f31SChris Mason extent_map_tree_empty_lru(&fs_info->block_group_cache); 796d10c5f31SChris Mason extent_map_tree_empty_lru(&fs_info->pinned_extents); 797d10c5f31SChris Mason extent_map_tree_empty_lru(&fs_info->pending_del); 798d10c5f31SChris Mason extent_map_tree_empty_lru(&fs_info->extent_ins); 79919c00ddcSChris Mason extent_map_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->extent_tree); 800d10c5f31SChris Mason 801db94535dSChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 802d10c5f31SChris Mason 803db94535dSChris Mason iput(fs_info->btree_inode); 80419c00ddcSChris Mason #if 0 80519c00ddcSChris Mason while(!list_empty(&fs_info->hashers)) { 80619c00ddcSChris Mason struct btrfs_hasher *hasher; 80719c00ddcSChris Mason hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher, 80819c00ddcSChris Mason hashers); 80919c00ddcSChris Mason list_del(&hasher->hashers); 81019c00ddcSChris Mason crypto_free_hash(&fs_info->hash_tfm); 81119c00ddcSChris Mason kfree(hasher); 81219c00ddcSChris Mason } 81319c00ddcSChris Mason #endif 8140f7d52f4SChris Mason kfree(fs_info->extent_root); 8150f7d52f4SChris Mason kfree(fs_info->tree_root); 816eb60ceacSChris Mason return 0; 817eb60ceacSChris Mason } 818eb60ceacSChris Mason 8195f39d397SChris Mason int btrfs_buffer_uptodate(struct extent_buffer *buf) 820ccd467d6SChris Mason { 821810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 8225f39d397SChris Mason return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf); 8235f39d397SChris Mason } 8246702ed49SChris Mason 8255f39d397SChris Mason int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 8265f39d397SChris Mason { 827810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 8285f39d397SChris Mason return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, 8295f39d397SChris Mason buf); 8305f39d397SChris Mason } 8315f39d397SChris Mason 8325f39d397SChris Mason void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 8335f39d397SChris Mason { 834810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8355f39d397SChris Mason u64 transid = btrfs_header_generation(buf); 8365f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8376702ed49SChris Mason 838ccd467d6SChris Mason if (transid != root->fs_info->generation) { 839ccd467d6SChris Mason printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 840db94535dSChris Mason (unsigned long long)buf->start, 841ccd467d6SChris Mason transid, root->fs_info->generation); 842ccd467d6SChris Mason WARN_ON(1); 843ccd467d6SChris Mason } 8445f39d397SChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); 845eb60ceacSChris Mason } 846eb60ceacSChris Mason 847d3c2fdcfSChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) 84835b7e476SChris Mason { 849d3c2fdcfSChris Mason balance_dirty_pages_ratelimited_nr( 850304fced6SChris Mason root->fs_info->btree_inode->i_mapping, 1); 85135b7e476SChris Mason } 8526b80053dSChris Mason 8536b80053dSChris Mason void btrfs_set_buffer_defrag(struct extent_buffer *buf) 8546b80053dSChris Mason { 855810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8566b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8576b80053dSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 8586b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 8596b80053dSChris Mason } 8606b80053dSChris Mason 8616b80053dSChris Mason void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 8626b80053dSChris Mason { 863810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8646b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8656b80053dSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 8666b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 8676b80053dSChris Mason GFP_NOFS); 8686b80053dSChris Mason } 8696b80053dSChris Mason 8706b80053dSChris Mason int btrfs_buffer_defrag(struct extent_buffer *buf) 8716b80053dSChris Mason { 872810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8736b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8746b80053dSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 8756b80053dSChris Mason buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 8766b80053dSChris Mason } 8776b80053dSChris Mason 8786b80053dSChris Mason int btrfs_buffer_defrag_done(struct extent_buffer *buf) 8796b80053dSChris Mason { 880810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8816b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8826b80053dSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 8836b80053dSChris Mason buf->start, buf->start + buf->len - 1, 8846b80053dSChris Mason EXTENT_DEFRAG_DONE, 0); 8856b80053dSChris Mason } 8866b80053dSChris Mason 8876b80053dSChris Mason int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 8886b80053dSChris Mason { 889810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8906b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8916b80053dSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 8926b80053dSChris Mason buf->start, buf->start + buf->len - 1, 8936b80053dSChris Mason EXTENT_DEFRAG_DONE, GFP_NOFS); 8946b80053dSChris Mason } 8956b80053dSChris Mason 8966b80053dSChris Mason int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 8976b80053dSChris Mason { 898810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8996b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 9006b80053dSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 9016b80053dSChris Mason buf->start, buf->start + buf->len - 1, 9026b80053dSChris Mason EXTENT_DEFRAG, GFP_NOFS); 9036b80053dSChris Mason } 9046b80053dSChris Mason 9056b80053dSChris Mason int btrfs_read_buffer(struct extent_buffer *buf) 9066b80053dSChris Mason { 907810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 9086b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 9096b80053dSChris Mason return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 91019c00ddcSChris Mason buf, 0, 1); 9116b80053dSChris Mason } 9120da5468fSChris Mason 9130da5468fSChris Mason static struct extent_map_ops btree_extent_map_ops = { 9140da5468fSChris Mason .writepage_io_hook = btree_writepage_io_hook, 9150da5468fSChris Mason }; 916