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 465f39d397SChris Mason struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 47db94535dSChris Mason u64 bytenr, u32 blocksize) 48eb60ceacSChris Mason { 495f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 50f510cfecSChris Mason struct extent_buffer *eb; 51f510cfecSChris Mason eb = find_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, 52db94535dSChris Mason bytenr, blocksize, GFP_NOFS); 53f510cfecSChris Mason return eb; 54e20d96d6SChris Mason } 555f39d397SChris Mason 565f39d397SChris Mason struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, 57db94535dSChris Mason u64 bytenr, u32 blocksize) 585f39d397SChris Mason { 595f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 60f510cfecSChris Mason struct extent_buffer *eb; 61db94535dSChris Mason 62f510cfecSChris Mason eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree, 6319c00ddcSChris Mason bytenr, blocksize, NULL, GFP_NOFS); 64f510cfecSChris Mason return eb; 65d98237b3SChris Mason } 665f39d397SChris Mason 675f39d397SChris Mason struct extent_map *btree_get_extent(struct inode *inode, struct page *page, 685f39d397SChris Mason size_t page_offset, u64 start, u64 end, 695f39d397SChris Mason int create) 705f39d397SChris Mason { 715f39d397SChris Mason struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 725f39d397SChris Mason struct extent_map *em; 735f39d397SChris Mason int ret; 745f39d397SChris Mason 755f39d397SChris Mason again: 765f39d397SChris Mason em = lookup_extent_mapping(em_tree, start, end); 775f39d397SChris Mason if (em) { 785f39d397SChris Mason goto out; 795f39d397SChris Mason } 805f39d397SChris Mason em = alloc_extent_map(GFP_NOFS); 815f39d397SChris Mason if (!em) { 825f39d397SChris Mason em = ERR_PTR(-ENOMEM); 835f39d397SChris Mason goto out; 845f39d397SChris Mason } 855f39d397SChris Mason em->start = 0; 865f39d397SChris Mason em->end = (i_size_read(inode) & ~((u64)PAGE_CACHE_SIZE -1)) - 1; 875f39d397SChris Mason em->block_start = 0; 885f39d397SChris Mason em->block_end = em->end; 895f39d397SChris Mason em->bdev = inode->i_sb->s_bdev; 905f39d397SChris Mason ret = add_extent_mapping(em_tree, em); 915f39d397SChris Mason if (ret == -EEXIST) { 925f39d397SChris Mason free_extent_map(em); 935f39d397SChris Mason em = NULL; 945f39d397SChris Mason goto again; 955f39d397SChris Mason } else if (ret) { 965f39d397SChris Mason em = ERR_PTR(ret); 975f39d397SChris Mason } 985f39d397SChris Mason out: 995f39d397SChris Mason return em; 1005f39d397SChris Mason } 1015f39d397SChris Mason 10219c00ddcSChris Mason u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 10319c00ddcSChris Mason { 10419c00ddcSChris Mason return crc32c(seed, data, len); 10519c00ddcSChris Mason } 10619c00ddcSChris Mason 10719c00ddcSChris Mason void btrfs_csum_final(u32 crc, char *result) 10819c00ddcSChris Mason { 10919c00ddcSChris Mason *(__le32 *)result = ~cpu_to_le32(crc); 11019c00ddcSChris Mason } 11119c00ddcSChris Mason 11219c00ddcSChris Mason static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 11319c00ddcSChris Mason int verify) 11419c00ddcSChris Mason { 11519c00ddcSChris Mason char result[BTRFS_CRC32_SIZE]; 11619c00ddcSChris Mason unsigned long len; 11719c00ddcSChris Mason unsigned long cur_len; 11819c00ddcSChris Mason unsigned long offset = BTRFS_CSUM_SIZE; 11919c00ddcSChris Mason char *map_token = NULL; 12019c00ddcSChris Mason char *kaddr; 12119c00ddcSChris Mason unsigned long map_start; 12219c00ddcSChris Mason unsigned long map_len; 12319c00ddcSChris Mason int err; 12419c00ddcSChris Mason u32 crc = ~(u32)0; 12519c00ddcSChris Mason 12619c00ddcSChris Mason len = buf->len - offset; 12719c00ddcSChris Mason while(len > 0) { 12819c00ddcSChris Mason err = map_private_extent_buffer(buf, offset, 32, 12919c00ddcSChris Mason &map_token, &kaddr, 13019c00ddcSChris Mason &map_start, &map_len, KM_USER0); 13119c00ddcSChris Mason if (err) { 13219c00ddcSChris Mason printk("failed to map extent buffer! %lu\n", 13319c00ddcSChris Mason offset); 13419c00ddcSChris Mason return 1; 13519c00ddcSChris Mason } 13619c00ddcSChris Mason cur_len = min(len, map_len - (offset - map_start)); 13719c00ddcSChris Mason crc = btrfs_csum_data(root, kaddr + offset - map_start, 13819c00ddcSChris Mason crc, cur_len); 13919c00ddcSChris Mason len -= cur_len; 14019c00ddcSChris Mason offset += cur_len; 14119c00ddcSChris Mason unmap_extent_buffer(buf, map_token, KM_USER0); 14219c00ddcSChris Mason } 14319c00ddcSChris Mason btrfs_csum_final(crc, result); 14419c00ddcSChris Mason 14519c00ddcSChris Mason if (verify) { 14619c00ddcSChris Mason if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 14719c00ddcSChris Mason printk("btrfs: %s checksum verify failed on %llu\n", 14819c00ddcSChris Mason root->fs_info->sb->s_id, 14919c00ddcSChris Mason buf->start); 15019c00ddcSChris Mason return 1; 15119c00ddcSChris Mason } 15219c00ddcSChris Mason } else { 15319c00ddcSChris Mason write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 15419c00ddcSChris Mason } 15519c00ddcSChris Mason return 0; 15619c00ddcSChris Mason } 15719c00ddcSChris Mason 15819c00ddcSChris Mason 15919c00ddcSChris Mason int csum_dirty_buffer(struct btrfs_root *root, struct page *page) 16019c00ddcSChris Mason { 16119c00ddcSChris Mason struct extent_map_tree *tree; 16219c00ddcSChris Mason u64 start = page->index << PAGE_CACHE_SHIFT; 16319c00ddcSChris Mason u64 found_start; 16419c00ddcSChris Mason int found_level; 16519c00ddcSChris Mason unsigned long len; 16619c00ddcSChris Mason struct extent_buffer *eb; 16719c00ddcSChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 16819c00ddcSChris Mason 16919c00ddcSChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 17019c00ddcSChris Mason goto out; 17119c00ddcSChris Mason if (!page->private) 17219c00ddcSChris Mason goto out; 17319c00ddcSChris Mason len = page->private >> 2; 17419c00ddcSChris Mason if (len == 0) { 17519c00ddcSChris Mason WARN_ON(1); 17619c00ddcSChris Mason } 17719c00ddcSChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 17819c00ddcSChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1); 17919c00ddcSChris Mason found_start = btrfs_header_bytenr(eb); 18019c00ddcSChris Mason if (found_start != start) { 18119c00ddcSChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 18219c00ddcSChris Mason start, found_start, len); 18319c00ddcSChris Mason } 18419c00ddcSChris Mason found_level = btrfs_header_level(eb); 18519c00ddcSChris Mason csum_tree_block(root, eb, 0); 18619c00ddcSChris Mason free_extent_buffer(eb); 18719c00ddcSChris Mason out: 18819c00ddcSChris Mason return 0; 18919c00ddcSChris Mason } 19019c00ddcSChris Mason 1915f39d397SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 1925f39d397SChris Mason { 1935f39d397SChris Mason struct extent_map_tree *tree; 19419c00ddcSChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 1955f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 19619c00ddcSChris Mason 19719c00ddcSChris Mason csum_dirty_buffer(root, page); 1985f39d397SChris Mason return extent_write_full_page(tree, page, btree_get_extent, wbc); 1995f39d397SChris Mason } 2005f39d397SChris Mason int btree_readpage(struct file *file, struct page *page) 2015f39d397SChris Mason { 2025f39d397SChris Mason struct extent_map_tree *tree; 2035f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2045f39d397SChris Mason return extent_read_full_page(tree, page, btree_get_extent); 2055f39d397SChris Mason } 2065f39d397SChris Mason 2075f39d397SChris Mason static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags) 2085f39d397SChris Mason { 2095f39d397SChris Mason struct extent_map_tree *tree; 2105f39d397SChris Mason int ret; 2115f39d397SChris Mason 2125f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2135f39d397SChris Mason ret = try_release_extent_mapping(tree, page); 2145f39d397SChris Mason if (ret == 1) { 2155f39d397SChris Mason ClearPagePrivate(page); 2165f39d397SChris Mason set_page_private(page, 0); 217d98237b3SChris Mason page_cache_release(page); 2185f39d397SChris Mason } 219d98237b3SChris Mason return ret; 220d98237b3SChris Mason } 221d98237b3SChris Mason 2225f39d397SChris Mason static void btree_invalidatepage(struct page *page, unsigned long offset) 223d98237b3SChris Mason { 2245f39d397SChris Mason struct extent_map_tree *tree; 2255f39d397SChris Mason tree = &BTRFS_I(page->mapping->host)->extent_tree; 2265f39d397SChris Mason extent_invalidatepage(tree, page, offset); 2275f39d397SChris Mason btree_releasepage(page, GFP_NOFS); 228d98237b3SChris Mason } 229d98237b3SChris Mason 2305f39d397SChris Mason #if 0 231d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 232d98237b3SChris Mason { 23387cbda5cSChris Mason struct buffer_head *bh; 2340f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 23587cbda5cSChris Mason struct buffer_head *head; 23687cbda5cSChris Mason if (!page_has_buffers(page)) { 23787cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 23887cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 23987cbda5cSChris Mason } 24087cbda5cSChris Mason head = page_buffers(page); 24187cbda5cSChris Mason bh = head; 24287cbda5cSChris Mason do { 24387cbda5cSChris Mason if (buffer_dirty(bh)) 24487cbda5cSChris Mason csum_tree_block(root, bh, 0); 24587cbda5cSChris Mason bh = bh->b_this_page; 24687cbda5cSChris Mason } while (bh != head); 247d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 248d98237b3SChris Mason } 2495f39d397SChris Mason #endif 250d98237b3SChris Mason 251d98237b3SChris Mason static struct address_space_operations btree_aops = { 252d98237b3SChris Mason .readpage = btree_readpage, 253d98237b3SChris Mason .writepage = btree_writepage, 2545f39d397SChris Mason .releasepage = btree_releasepage, 2555f39d397SChris Mason .invalidatepage = btree_invalidatepage, 256d98237b3SChris Mason .sync_page = block_sync_page, 257d98237b3SChris Mason }; 258123abc88SChris Mason 259db94535dSChris Mason int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) 260090d1875SChris Mason { 2615f39d397SChris Mason struct extent_buffer *buf = NULL; 2625f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 263de428b63SChris Mason int ret = 0; 264090d1875SChris Mason 265db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 2665f39d397SChris Mason if (!buf) 267090d1875SChris Mason return 0; 2685f39d397SChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 26919c00ddcSChris Mason buf, 0, 0); 2705f39d397SChris Mason free_extent_buffer(buf); 271de428b63SChris Mason return ret; 272090d1875SChris Mason } 273090d1875SChris Mason 274db94535dSChris Mason struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 275db94535dSChris Mason u32 blocksize) 276e20d96d6SChris Mason { 2775f39d397SChris Mason struct extent_buffer *buf = NULL; 2785f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 27919c00ddcSChris Mason struct extent_map_tree *extent_tree; 28019c00ddcSChris Mason int ret; 28119c00ddcSChris Mason 28219c00ddcSChris Mason extent_tree = &BTRFS_I(btree_inode)->extent_tree; 283e20d96d6SChris Mason 284db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 2855f39d397SChris Mason if (!buf) 286d98237b3SChris Mason return NULL; 2875f39d397SChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 28819c00ddcSChris Mason buf, 0, 1); 28919c00ddcSChris Mason if (buf->flags & EXTENT_CSUM) { 29019c00ddcSChris Mason return buf; 29119c00ddcSChris Mason } 29219c00ddcSChris Mason if (test_range_bit(extent_tree, buf->start, buf->start + buf->len - 1, 29319c00ddcSChris Mason EXTENT_CSUM, 1)) { 29419c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 29519c00ddcSChris Mason return buf; 29619c00ddcSChris Mason } 29719c00ddcSChris Mason ret = csum_tree_block(root, buf, 1); 29819c00ddcSChris Mason set_extent_bits(extent_tree, buf->start, 29919c00ddcSChris Mason buf->start + buf->len - 1, 30019c00ddcSChris Mason EXTENT_CSUM, GFP_NOFS); 30119c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 3025f39d397SChris Mason return buf; 303eb60ceacSChris Mason } 304eb60ceacSChris Mason 305e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 3065f39d397SChris Mason struct extent_buffer *buf) 307ed2ff2cbSChris Mason { 3085f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 3095f39d397SChris Mason clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); 3105f39d397SChris Mason return 0; 3115f39d397SChris Mason } 3125f39d397SChris Mason 3135f39d397SChris Mason int wait_on_tree_block_writeback(struct btrfs_root *root, 3145f39d397SChris Mason struct extent_buffer *buf) 3155f39d397SChris Mason { 3165f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 3175f39d397SChris Mason wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->extent_tree, 3185f39d397SChris Mason buf); 3195f39d397SChris Mason return 0; 3205f39d397SChris Mason } 3215f39d397SChris Mason 322db94535dSChris Mason static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 3239f5fae2fSChris Mason struct btrfs_root *root, 3249f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 325e20d96d6SChris Mason u64 objectid) 326d97e63b6SChris Mason { 327cfaa7295SChris Mason root->node = NULL; 3280f7d52f4SChris Mason root->inode = NULL; 329a28ec197SChris Mason root->commit_root = NULL; 330db94535dSChris Mason root->sectorsize = sectorsize; 331db94535dSChris Mason root->nodesize = nodesize; 332db94535dSChris Mason root->leafsize = leafsize; 333123abc88SChris Mason root->ref_cows = 0; 3349f5fae2fSChris Mason root->fs_info = fs_info; 3350f7d52f4SChris Mason root->objectid = objectid; 3360f7d52f4SChris Mason root->last_trans = 0; 3371b05da2eSChris Mason root->highest_inode = 0; 3381b05da2eSChris Mason root->last_inode_alloc = 0; 33958176a96SJosef Bacik root->name = NULL; 3403768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 3413768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 3426702ed49SChris Mason memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 34358176a96SJosef Bacik memset(&root->root_kobj, 0, sizeof(root->root_kobj)); 34458176a96SJosef Bacik init_completion(&root->kobj_unregister); 345011410bdSChris Mason init_rwsem(&root->snap_sem); 3466702ed49SChris Mason root->defrag_running = 0; 3476702ed49SChris Mason root->defrag_level = 0; 3484d775673SChris Mason root->root_key.objectid = objectid; 3493768f368SChris Mason return 0; 3503768f368SChris Mason } 3513768f368SChris Mason 352db94535dSChris Mason static int find_and_setup_root(struct btrfs_root *tree_root, 3539f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 3549f5fae2fSChris Mason u64 objectid, 355e20d96d6SChris Mason struct btrfs_root *root) 3563768f368SChris Mason { 3573768f368SChris Mason int ret; 358db94535dSChris Mason u32 blocksize; 3593768f368SChris Mason 360db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 361db94535dSChris Mason tree_root->sectorsize, root, fs_info, objectid); 3623768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 3633768f368SChris Mason &root->root_item, &root->root_key); 3643768f368SChris Mason BUG_ON(ret); 3653768f368SChris Mason 366db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 367db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 368db94535dSChris Mason blocksize); 3693768f368SChris Mason BUG_ON(!root->node); 370d97e63b6SChris Mason return 0; 371d97e63b6SChris Mason } 372d97e63b6SChris Mason 3735eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 3740f7d52f4SChris Mason struct btrfs_key *location) 3750f7d52f4SChris Mason { 3760f7d52f4SChris Mason struct btrfs_root *root; 3770f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 3780f7d52f4SChris Mason struct btrfs_path *path; 3795f39d397SChris Mason struct extent_buffer *l; 3801b05da2eSChris Mason u64 highest_inode; 381db94535dSChris Mason u32 blocksize; 3820f7d52f4SChris Mason int ret = 0; 3830f7d52f4SChris Mason 3845eda7b5eSChris Mason root = kzalloc(sizeof(*root), GFP_NOFS); 3850cf6c620SChris Mason if (!root) 3860f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 3870f7d52f4SChris Mason if (location->offset == (u64)-1) { 388db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 3890f7d52f4SChris Mason location->objectid, root); 3900f7d52f4SChris Mason if (ret) { 3910f7d52f4SChris Mason kfree(root); 3920f7d52f4SChris Mason return ERR_PTR(ret); 3930f7d52f4SChris Mason } 3940f7d52f4SChris Mason goto insert; 3950f7d52f4SChris Mason } 3960f7d52f4SChris Mason 397db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 398db94535dSChris Mason tree_root->sectorsize, root, fs_info, 3990f7d52f4SChris Mason location->objectid); 4000f7d52f4SChris Mason 4010f7d52f4SChris Mason path = btrfs_alloc_path(); 4020f7d52f4SChris Mason BUG_ON(!path); 4030f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 4040f7d52f4SChris Mason if (ret != 0) { 4050f7d52f4SChris Mason if (ret > 0) 4060f7d52f4SChris Mason ret = -ENOENT; 4070f7d52f4SChris Mason goto out; 4080f7d52f4SChris Mason } 4095f39d397SChris Mason l = path->nodes[0]; 4105f39d397SChris Mason read_extent_buffer(l, &root->root_item, 4115f39d397SChris Mason btrfs_item_ptr_offset(l, path->slots[0]), 4120f7d52f4SChris Mason sizeof(root->root_item)); 4130f7d52f4SChris Mason ret = 0; 4140f7d52f4SChris Mason out: 4150f7d52f4SChris Mason btrfs_release_path(root, path); 4160f7d52f4SChris Mason btrfs_free_path(path); 4170f7d52f4SChris Mason if (ret) { 4180f7d52f4SChris Mason kfree(root); 4190f7d52f4SChris Mason return ERR_PTR(ret); 4200f7d52f4SChris Mason } 421db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 422db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 423db94535dSChris Mason blocksize); 4240f7d52f4SChris Mason BUG_ON(!root->node); 4250f7d52f4SChris Mason insert: 4260f7d52f4SChris Mason root->ref_cows = 1; 4275eda7b5eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 4285eda7b5eSChris Mason if (ret == 0) { 4295eda7b5eSChris Mason root->highest_inode = highest_inode; 4305eda7b5eSChris Mason root->last_inode_alloc = highest_inode; 4315eda7b5eSChris Mason } 4325eda7b5eSChris Mason return root; 4335eda7b5eSChris Mason } 4345eda7b5eSChris Mason 4355eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 43658176a96SJosef Bacik struct btrfs_key *location, 43758176a96SJosef Bacik const char *name, int namelen) 4385eda7b5eSChris Mason { 4395eda7b5eSChris Mason struct btrfs_root *root; 4405eda7b5eSChris Mason int ret; 4415eda7b5eSChris Mason 4425eda7b5eSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 4435eda7b5eSChris Mason (unsigned long)location->objectid); 4445eda7b5eSChris Mason if (root) 4455eda7b5eSChris Mason return root; 4465eda7b5eSChris Mason 4475eda7b5eSChris Mason root = btrfs_read_fs_root_no_radix(fs_info, location); 4485eda7b5eSChris Mason if (IS_ERR(root)) 4495eda7b5eSChris Mason return root; 4502619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 4512619ba1fSChris Mason (unsigned long)root->root_key.objectid, 4520f7d52f4SChris Mason root); 4530f7d52f4SChris Mason if (ret) { 4545f39d397SChris Mason free_extent_buffer(root->node); 4550f7d52f4SChris Mason kfree(root); 4560f7d52f4SChris Mason return ERR_PTR(ret); 4570f7d52f4SChris Mason } 45858176a96SJosef Bacik 45958176a96SJosef Bacik ret = btrfs_set_root_name(root, name, namelen); 46058176a96SJosef Bacik if (ret) { 4615f39d397SChris Mason free_extent_buffer(root->node); 46258176a96SJosef Bacik kfree(root); 46358176a96SJosef Bacik return ERR_PTR(ret); 46458176a96SJosef Bacik } 46558176a96SJosef Bacik 46658176a96SJosef Bacik ret = btrfs_sysfs_add_root(root); 46758176a96SJosef Bacik if (ret) { 4685f39d397SChris Mason free_extent_buffer(root->node); 46958176a96SJosef Bacik kfree(root->name); 47058176a96SJosef Bacik kfree(root); 47158176a96SJosef Bacik return ERR_PTR(ret); 47258176a96SJosef Bacik } 47358176a96SJosef Bacik 4745ce14bbcSChris Mason ret = btrfs_find_dead_roots(fs_info->tree_root, 4755ce14bbcSChris Mason root->root_key.objectid, root); 4765ce14bbcSChris Mason BUG_ON(ret); 4775ce14bbcSChris Mason 4780f7d52f4SChris Mason return root; 4790f7d52f4SChris Mason } 48019c00ddcSChris Mason #if 0 48119c00ddcSChris Mason static int add_hasher(struct btrfs_fs_info *info, char *type) { 48219c00ddcSChris Mason struct btrfs_hasher *hasher; 4830f7d52f4SChris Mason 48419c00ddcSChris Mason hasher = kmalloc(sizeof(*hasher), GFP_NOFS); 48519c00ddcSChris Mason if (!hasher) 48619c00ddcSChris Mason return -ENOMEM; 48719c00ddcSChris Mason hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC); 48819c00ddcSChris Mason if (!hasher->hash_tfm) { 48919c00ddcSChris Mason kfree(hasher); 49019c00ddcSChris Mason return -EINVAL; 49119c00ddcSChris Mason } 49219c00ddcSChris Mason spin_lock(&info->hash_lock); 49319c00ddcSChris Mason list_add(&hasher->list, &info->hashers); 49419c00ddcSChris Mason spin_unlock(&info->hash_lock); 49519c00ddcSChris Mason return 0; 49619c00ddcSChris Mason } 49719c00ddcSChris Mason #endif 4982c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 499eb60ceacSChris Mason { 500db94535dSChris Mason u32 sectorsize; 501db94535dSChris Mason u32 nodesize; 502db94535dSChris Mason u32 leafsize; 503db94535dSChris Mason u32 blocksize; 504e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 505e20d96d6SChris Mason GFP_NOFS); 506e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 507e20d96d6SChris Mason GFP_NOFS); 508e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 509e20d96d6SChris Mason GFP_NOFS); 510eb60ceacSChris Mason int ret; 51139279cc3SChris Mason int err = -EIO; 5122c90e5d6SChris Mason struct btrfs_super_block *disk_super; 513eb60ceacSChris Mason 51439279cc3SChris Mason if (!extent_root || !tree_root || !fs_info) { 51539279cc3SChris Mason err = -ENOMEM; 51639279cc3SChris Mason goto fail; 51739279cc3SChris Mason } 5180f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 5198fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 520facda1e7SChris Mason INIT_LIST_HEAD(&fs_info->dead_roots); 52119c00ddcSChris Mason INIT_LIST_HEAD(&fs_info->hashers); 52219c00ddcSChris Mason spin_lock_init(&fs_info->hash_lock); 52319c00ddcSChris Mason 52458176a96SJosef Bacik memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj)); 52558176a96SJosef Bacik init_completion(&fs_info->kobj_unregister); 5262c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 5279f5fae2fSChris Mason fs_info->running_transaction = NULL; 52815ee9bc7SJosef Bacik fs_info->last_trans_committed = 0; 5299f5fae2fSChris Mason fs_info->tree_root = tree_root; 5309f5fae2fSChris Mason fs_info->extent_root = extent_root; 531e20d96d6SChris Mason fs_info->sb = sb; 532d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 533d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 5342c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 535d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 536d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 5375f39d397SChris Mason extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, 5385f39d397SChris Mason fs_info->btree_inode->i_mapping, 5395f39d397SChris Mason GFP_NOFS); 540f510cfecSChris Mason extent_map_tree_init(&fs_info->free_space_cache, 541f510cfecSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 54296b5179dSChris Mason extent_map_tree_init(&fs_info->block_group_cache, 54396b5179dSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 5441a5bc167SChris Mason extent_map_tree_init(&fs_info->pinned_extents, 5451a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 5461a5bc167SChris Mason extent_map_tree_init(&fs_info->pending_del, 5471a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 5481a5bc167SChris Mason extent_map_tree_init(&fs_info->extent_ins, 5491a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 550e66f709bSChris Mason fs_info->do_barriers = 1; 551facda1e7SChris Mason fs_info->closing = 0; 552facda1e7SChris Mason 55308607c1bSChris Mason INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 5540f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 5550f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 5560f7d52f4SChris Mason sizeof(struct btrfs_key)); 55722b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 558d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 55939279cc3SChris Mason 56079154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 561d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 5623768f368SChris Mason 56319c00ddcSChris Mason #if 0 56419c00ddcSChris Mason ret = add_hasher(fs_info, "crc32c"); 56519c00ddcSChris Mason if (ret) { 56619c00ddcSChris Mason printk("btrfs: failed hash setup, modprobe cryptomgr?\n"); 56719c00ddcSChris Mason err = -ENOMEM; 56819c00ddcSChris Mason goto fail_iput; 56919c00ddcSChris Mason } 57019c00ddcSChris Mason #endif 571db94535dSChris Mason __setup_root(512, 512, 512, tree_root, 5722c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 5737eccb903SChris Mason 5742c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 575db94535dSChris Mason BTRFS_SUPER_INFO_OFFSET, 576db94535dSChris Mason 512); 577d98237b3SChris Mason 5780f7d52f4SChris Mason if (!fs_info->sb_buffer) 57939279cc3SChris Mason goto fail_iput; 58039279cc3SChris Mason 5815f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, 5825f39d397SChris Mason sizeof(fs_info->super_copy)); 5835f39d397SChris Mason 5845f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, 5855f39d397SChris Mason (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), 5865f39d397SChris Mason BTRFS_FSID_SIZE); 5875f39d397SChris Mason disk_super = &fs_info->super_copy; 5880f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 58939279cc3SChris Mason goto fail_sb_buffer; 5900f7d52f4SChris Mason 591db94535dSChris Mason nodesize = btrfs_super_nodesize(disk_super); 592db94535dSChris Mason leafsize = btrfs_super_leafsize(disk_super); 593db94535dSChris Mason sectorsize = btrfs_super_sectorsize(disk_super); 594db94535dSChris Mason tree_root->nodesize = nodesize; 595db94535dSChris Mason tree_root->leafsize = leafsize; 596db94535dSChris Mason tree_root->sectorsize = sectorsize; 597db94535dSChris Mason 5988352d8a4SChris Mason i_size_write(fs_info->btree_inode, 599db94535dSChris Mason btrfs_super_total_bytes(disk_super)); 6008352d8a4SChris Mason 60139279cc3SChris Mason if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 60239279cc3SChris Mason sizeof(disk_super->magic))) { 60339279cc3SChris Mason printk("btrfs: valid FS not found on %s\n", sb->s_id); 60439279cc3SChris Mason goto fail_sb_buffer; 60539279cc3SChris Mason } 60619c00ddcSChris Mason 607db94535dSChris Mason blocksize = btrfs_level_size(tree_root, 608db94535dSChris Mason btrfs_super_root_level(disk_super)); 60919c00ddcSChris Mason 610e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 611db94535dSChris Mason btrfs_super_root(disk_super), 612db94535dSChris Mason blocksize); 61339279cc3SChris Mason if (!tree_root->node) 61439279cc3SChris Mason goto fail_sb_buffer; 6153768f368SChris Mason 6162c90e5d6SChris Mason mutex_lock(&fs_info->fs_mutex); 617db94535dSChris Mason 618db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 619e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 62039279cc3SChris Mason if (ret) { 62139279cc3SChris Mason mutex_unlock(&fs_info->fs_mutex); 62239279cc3SChris Mason goto fail_tree_root; 62339279cc3SChris Mason } 6243768f368SChris Mason 6259078a3e1SChris Mason btrfs_read_block_groups(extent_root); 6269078a3e1SChris Mason 6270f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 6285be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 6290f7d52f4SChris Mason return tree_root; 63039279cc3SChris Mason 63139279cc3SChris Mason fail_tree_root: 6325f39d397SChris Mason free_extent_buffer(tree_root->node); 63339279cc3SChris Mason fail_sb_buffer: 6345f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 63539279cc3SChris Mason fail_iput: 63639279cc3SChris Mason iput(fs_info->btree_inode); 63739279cc3SChris Mason fail: 63839279cc3SChris Mason kfree(extent_root); 63939279cc3SChris Mason kfree(tree_root); 64039279cc3SChris Mason kfree(fs_info); 64139279cc3SChris Mason return ERR_PTR(err); 642eb60ceacSChris Mason } 643eb60ceacSChris Mason 644e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 64579154b1bSChris Mason *root) 646cfaa7295SChris Mason { 647e66f709bSChris Mason int ret; 6485f39d397SChris Mason struct extent_buffer *super = root->fs_info->sb_buffer; 6495f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 6502c90e5d6SChris Mason 6515f39d397SChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, super); 6525f39d397SChris Mason ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, 6535f39d397SChris Mason super->start, super->len); 6545f39d397SChris Mason return ret; 655cfaa7295SChris Mason } 656cfaa7295SChris Mason 6575eda7b5eSChris Mason int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 6582619ba1fSChris Mason { 6592619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 6602619ba1fSChris Mason (unsigned long)root->root_key.objectid); 66158176a96SJosef Bacik btrfs_sysfs_del_root(root); 6622619ba1fSChris Mason if (root->inode) 6632619ba1fSChris Mason iput(root->inode); 6642619ba1fSChris Mason if (root->node) 6655f39d397SChris Mason free_extent_buffer(root->node); 6662619ba1fSChris Mason if (root->commit_root) 6675f39d397SChris Mason free_extent_buffer(root->commit_root); 66858176a96SJosef Bacik if (root->name) 66958176a96SJosef Bacik kfree(root->name); 6702619ba1fSChris Mason kfree(root); 6712619ba1fSChris Mason return 0; 6722619ba1fSChris Mason } 6732619ba1fSChris Mason 67435b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 6750f7d52f4SChris Mason { 6760f7d52f4SChris Mason int ret; 6770f7d52f4SChris Mason struct btrfs_root *gang[8]; 6780f7d52f4SChris Mason int i; 6790f7d52f4SChris Mason 6800f7d52f4SChris Mason while(1) { 6810f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 6820f7d52f4SChris Mason (void **)gang, 0, 6830f7d52f4SChris Mason ARRAY_SIZE(gang)); 6840f7d52f4SChris Mason if (!ret) 6850f7d52f4SChris Mason break; 6862619ba1fSChris Mason for (i = 0; i < ret; i++) 6875eda7b5eSChris Mason btrfs_free_fs_root(fs_info, gang[i]); 6880f7d52f4SChris Mason } 6890f7d52f4SChris Mason return 0; 6900f7d52f4SChris Mason } 691b4100d64SChris Mason 692e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 693eb60ceacSChris Mason { 6943768f368SChris Mason int ret; 695e089f05cSChris Mason struct btrfs_trans_handle *trans; 6960f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 697e089f05cSChris Mason 698facda1e7SChris Mason fs_info->closing = 1; 69908607c1bSChris Mason btrfs_transaction_flush_work(root); 7000f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 7016702ed49SChris Mason btrfs_defrag_dirty_roots(root->fs_info); 70279154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 70354aa1f4dSChris Mason ret = btrfs_commit_transaction(trans, root); 70479154b1bSChris Mason /* run commit again to drop the original snapshot */ 70579154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 70679154b1bSChris Mason btrfs_commit_transaction(trans, root); 70779154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 7089f5fae2fSChris Mason BUG_ON(ret); 70979154b1bSChris Mason write_ctree_super(NULL, root); 7100f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 711ed2ff2cbSChris Mason 7120f7d52f4SChris Mason if (fs_info->extent_root->node) 7135f39d397SChris Mason free_extent_buffer(fs_info->extent_root->node); 714f510cfecSChris Mason 7150f7d52f4SChris Mason if (fs_info->tree_root->node) 7165f39d397SChris Mason free_extent_buffer(fs_info->tree_root->node); 717f510cfecSChris Mason 7185f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 7197eccb903SChris Mason 7209078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 7210f7d52f4SChris Mason del_fs_roots(fs_info); 72219c00ddcSChris Mason extent_map_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->extent_tree); 723db94535dSChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 724db94535dSChris Mason iput(fs_info->btree_inode); 72519c00ddcSChris Mason #if 0 72619c00ddcSChris Mason while(!list_empty(&fs_info->hashers)) { 72719c00ddcSChris Mason struct btrfs_hasher *hasher; 72819c00ddcSChris Mason hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher, 72919c00ddcSChris Mason hashers); 73019c00ddcSChris Mason list_del(&hasher->hashers); 73119c00ddcSChris Mason crypto_free_hash(&fs_info->hash_tfm); 73219c00ddcSChris Mason kfree(hasher); 73319c00ddcSChris Mason } 73419c00ddcSChris Mason #endif 7350f7d52f4SChris Mason kfree(fs_info->extent_root); 7360f7d52f4SChris Mason kfree(fs_info->tree_root); 737eb60ceacSChris Mason return 0; 738eb60ceacSChris Mason } 739eb60ceacSChris Mason 7405f39d397SChris Mason int btrfs_buffer_uptodate(struct extent_buffer *buf) 741ccd467d6SChris Mason { 742810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 7435f39d397SChris Mason return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf); 7445f39d397SChris Mason } 7456702ed49SChris Mason 7465f39d397SChris Mason int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 7475f39d397SChris Mason { 748810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 7495f39d397SChris Mason return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, 7505f39d397SChris Mason buf); 7515f39d397SChris Mason } 7525f39d397SChris Mason 7535f39d397SChris Mason void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 7545f39d397SChris Mason { 755810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 7565f39d397SChris Mason u64 transid = btrfs_header_generation(buf); 7575f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 7586702ed49SChris Mason 759ccd467d6SChris Mason if (transid != root->fs_info->generation) { 760ccd467d6SChris Mason printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 761db94535dSChris Mason (unsigned long long)buf->start, 762ccd467d6SChris Mason transid, root->fs_info->generation); 763ccd467d6SChris Mason WARN_ON(1); 764ccd467d6SChris Mason } 7655f39d397SChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); 766eb60ceacSChris Mason } 767eb60ceacSChris Mason 768d3c2fdcfSChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) 76935b7e476SChris Mason { 770d3c2fdcfSChris Mason balance_dirty_pages_ratelimited_nr( 771d3c2fdcfSChris Mason root->fs_info->btree_inode->i_mapping, nr); 77235b7e476SChris Mason } 7736b80053dSChris Mason 7746b80053dSChris Mason void btrfs_set_buffer_defrag(struct extent_buffer *buf) 7756b80053dSChris Mason { 776810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 7776b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 7786b80053dSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 7796b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 7806b80053dSChris Mason } 7816b80053dSChris Mason 7826b80053dSChris Mason void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 7836b80053dSChris Mason { 784810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 7856b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 7866b80053dSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 7876b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 7886b80053dSChris Mason GFP_NOFS); 7896b80053dSChris Mason } 7906b80053dSChris Mason 7916b80053dSChris Mason int btrfs_buffer_defrag(struct extent_buffer *buf) 7926b80053dSChris Mason { 793810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 7946b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 7956b80053dSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 7966b80053dSChris Mason buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 7976b80053dSChris Mason } 7986b80053dSChris Mason 7996b80053dSChris Mason int btrfs_buffer_defrag_done(struct extent_buffer *buf) 8006b80053dSChris Mason { 801810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8026b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8036b80053dSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 8046b80053dSChris Mason buf->start, buf->start + buf->len - 1, 8056b80053dSChris Mason EXTENT_DEFRAG_DONE, 0); 8066b80053dSChris Mason } 8076b80053dSChris Mason 8086b80053dSChris Mason int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 8096b80053dSChris Mason { 810810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8116b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8126b80053dSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 8136b80053dSChris Mason buf->start, buf->start + buf->len - 1, 8146b80053dSChris Mason EXTENT_DEFRAG_DONE, GFP_NOFS); 8156b80053dSChris Mason } 8166b80053dSChris Mason 8176b80053dSChris Mason int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 8186b80053dSChris Mason { 819810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8206b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8216b80053dSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 8226b80053dSChris Mason buf->start, buf->start + buf->len - 1, 8236b80053dSChris Mason EXTENT_DEFRAG, GFP_NOFS); 8246b80053dSChris Mason } 8256b80053dSChris Mason 8266b80053dSChris Mason int btrfs_read_buffer(struct extent_buffer *buf) 8276b80053dSChris Mason { 828810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 8296b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 8306b80053dSChris Mason return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 83119c00ddcSChris Mason buf, 0, 1); 8326b80053dSChris Mason } 833