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" 310b86a832SChris Mason #include "volumes.h" 32db94535dSChris Mason #include "print-tree.h" 33eb60ceacSChris Mason 345f39d397SChris Mason #if 0 355f39d397SChris Mason static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) 367eccb903SChris Mason { 375f39d397SChris Mason if (extent_buffer_blocknr(buf) != btrfs_header_blocknr(buf)) { 385f39d397SChris Mason printk(KERN_CRIT "buf blocknr(buf) is %llu, header is %llu\n", 395f39d397SChris Mason (unsigned long long)extent_buffer_blocknr(buf), 405f39d397SChris Mason (unsigned long long)btrfs_header_blocknr(buf)); 4139279cc3SChris Mason return 1; 42d98237b3SChris Mason } 439a8dd150SChris Mason return 0; 44eb60ceacSChris Mason } 455f39d397SChris Mason #endif 46eb60ceacSChris Mason 47d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops; 480da5468fSChris Mason 495f39d397SChris Mason struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 50db94535dSChris Mason u64 bytenr, u32 blocksize) 51eb60ceacSChris Mason { 525f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 53f510cfecSChris Mason struct extent_buffer *eb; 54d1310b2eSChris Mason eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 55db94535dSChris Mason bytenr, blocksize, GFP_NOFS); 56f510cfecSChris Mason return eb; 57e20d96d6SChris Mason } 585f39d397SChris Mason 595f39d397SChris Mason struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, 60db94535dSChris Mason u64 bytenr, u32 blocksize) 615f39d397SChris Mason { 625f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 63f510cfecSChris Mason struct extent_buffer *eb; 64db94535dSChris Mason 65d1310b2eSChris Mason eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 6619c00ddcSChris Mason bytenr, blocksize, NULL, GFP_NOFS); 67f510cfecSChris Mason return eb; 68d98237b3SChris Mason } 695f39d397SChris Mason 705f39d397SChris Mason struct extent_map *btree_get_extent(struct inode *inode, struct page *page, 71d1310b2eSChris Mason size_t page_offset, u64 start, u64 len, 725f39d397SChris Mason int create) 735f39d397SChris Mason { 745f39d397SChris Mason struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 755f39d397SChris Mason struct extent_map *em; 765f39d397SChris Mason int ret; 775f39d397SChris Mason 785f39d397SChris Mason again: 79d1310b2eSChris Mason spin_lock(&em_tree->lock); 80d1310b2eSChris Mason em = lookup_extent_mapping(em_tree, start, len); 81d1310b2eSChris Mason spin_unlock(&em_tree->lock); 825f39d397SChris Mason if (em) { 835f39d397SChris Mason goto out; 845f39d397SChris Mason } 855f39d397SChris Mason em = alloc_extent_map(GFP_NOFS); 865f39d397SChris Mason if (!em) { 875f39d397SChris Mason em = ERR_PTR(-ENOMEM); 885f39d397SChris Mason goto out; 895f39d397SChris Mason } 905f39d397SChris Mason em->start = 0; 91d1310b2eSChris Mason em->len = i_size_read(inode); 925f39d397SChris Mason em->block_start = 0; 935f39d397SChris Mason em->bdev = inode->i_sb->s_bdev; 94d1310b2eSChris Mason 95d1310b2eSChris Mason spin_lock(&em_tree->lock); 965f39d397SChris Mason ret = add_extent_mapping(em_tree, em); 97d1310b2eSChris Mason spin_unlock(&em_tree->lock); 98d1310b2eSChris Mason 995f39d397SChris Mason if (ret == -EEXIST) { 1005f39d397SChris Mason free_extent_map(em); 1015f39d397SChris Mason em = NULL; 1025f39d397SChris Mason goto again; 1035f39d397SChris Mason } else if (ret) { 1045f39d397SChris Mason em = ERR_PTR(ret); 1055f39d397SChris Mason } 1065f39d397SChris Mason out: 1075f39d397SChris Mason return em; 1085f39d397SChris Mason } 1095f39d397SChris Mason 11019c00ddcSChris Mason u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 11119c00ddcSChris Mason { 11219c00ddcSChris Mason return crc32c(seed, data, len); 11319c00ddcSChris Mason } 11419c00ddcSChris Mason 11519c00ddcSChris Mason void btrfs_csum_final(u32 crc, char *result) 11619c00ddcSChris Mason { 11719c00ddcSChris Mason *(__le32 *)result = ~cpu_to_le32(crc); 11819c00ddcSChris Mason } 11919c00ddcSChris Mason 12019c00ddcSChris Mason static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 12119c00ddcSChris Mason int verify) 12219c00ddcSChris Mason { 12319c00ddcSChris Mason char result[BTRFS_CRC32_SIZE]; 12419c00ddcSChris Mason unsigned long len; 12519c00ddcSChris Mason unsigned long cur_len; 12619c00ddcSChris Mason unsigned long offset = BTRFS_CSUM_SIZE; 12719c00ddcSChris Mason char *map_token = NULL; 12819c00ddcSChris Mason char *kaddr; 12919c00ddcSChris Mason unsigned long map_start; 13019c00ddcSChris Mason unsigned long map_len; 13119c00ddcSChris Mason int err; 13219c00ddcSChris Mason u32 crc = ~(u32)0; 13319c00ddcSChris Mason 13419c00ddcSChris Mason len = buf->len - offset; 13519c00ddcSChris Mason while(len > 0) { 13619c00ddcSChris Mason err = map_private_extent_buffer(buf, offset, 32, 13719c00ddcSChris Mason &map_token, &kaddr, 13819c00ddcSChris Mason &map_start, &map_len, KM_USER0); 13919c00ddcSChris Mason if (err) { 14019c00ddcSChris Mason printk("failed to map extent buffer! %lu\n", 14119c00ddcSChris Mason offset); 14219c00ddcSChris Mason return 1; 14319c00ddcSChris Mason } 14419c00ddcSChris Mason cur_len = min(len, map_len - (offset - map_start)); 14519c00ddcSChris Mason crc = btrfs_csum_data(root, kaddr + offset - map_start, 14619c00ddcSChris Mason crc, cur_len); 14719c00ddcSChris Mason len -= cur_len; 14819c00ddcSChris Mason offset += cur_len; 14919c00ddcSChris Mason unmap_extent_buffer(buf, map_token, KM_USER0); 15019c00ddcSChris Mason } 15119c00ddcSChris Mason btrfs_csum_final(crc, result); 15219c00ddcSChris Mason 15319c00ddcSChris Mason if (verify) { 154e4204dedSChris Mason int from_this_trans = 0; 155e4204dedSChris Mason 156e4204dedSChris Mason if (root->fs_info->running_transaction && 157e4204dedSChris Mason btrfs_header_generation(buf) == 158e4204dedSChris Mason root->fs_info->running_transaction->transid) 159e4204dedSChris Mason from_this_trans = 1; 160e4204dedSChris Mason 161e4204dedSChris Mason /* FIXME, this is not good */ 162e4204dedSChris Mason if (from_this_trans == 0 && 163e4204dedSChris Mason memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 164e4204dedSChris Mason u32 val; 165e4204dedSChris Mason u32 found = 0; 166e4204dedSChris Mason memcpy(&found, result, BTRFS_CRC32_SIZE); 167e4204dedSChris Mason 168e4204dedSChris Mason read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE); 169e4204dedSChris Mason printk("btrfs: %s checksum verify failed on %llu " 170e4204dedSChris Mason "wanted %X found %X from_this_trans %d\n", 17119c00ddcSChris Mason root->fs_info->sb->s_id, 172e4204dedSChris Mason buf->start, val, found, from_this_trans); 17319c00ddcSChris Mason return 1; 17419c00ddcSChris Mason } 17519c00ddcSChris Mason } else { 17619c00ddcSChris Mason write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 17719c00ddcSChris Mason } 17819c00ddcSChris Mason return 0; 17919c00ddcSChris Mason } 18019c00ddcSChris Mason 18119c00ddcSChris Mason 18219c00ddcSChris Mason int csum_dirty_buffer(struct btrfs_root *root, struct page *page) 18319c00ddcSChris Mason { 184d1310b2eSChris Mason struct extent_io_tree *tree; 18535ebb934SChris Mason u64 start = (u64)page->index << PAGE_CACHE_SHIFT; 18619c00ddcSChris Mason u64 found_start; 18719c00ddcSChris Mason int found_level; 18819c00ddcSChris Mason unsigned long len; 18919c00ddcSChris Mason struct extent_buffer *eb; 190d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 19119c00ddcSChris Mason 19219c00ddcSChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 19319c00ddcSChris Mason goto out; 19419c00ddcSChris Mason if (!page->private) 19519c00ddcSChris Mason goto out; 19619c00ddcSChris Mason len = page->private >> 2; 19719c00ddcSChris Mason if (len == 0) { 19819c00ddcSChris Mason WARN_ON(1); 19919c00ddcSChris Mason } 20019c00ddcSChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 201a86c12c7SChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1, 202a86c12c7SChris Mason btree_get_extent); 203e18e4809SChris Mason btrfs_clear_buffer_defrag(eb); 20419c00ddcSChris Mason found_start = btrfs_header_bytenr(eb); 20519c00ddcSChris Mason if (found_start != start) { 20619c00ddcSChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 20719c00ddcSChris Mason start, found_start, len); 20855c69072SChris Mason WARN_ON(1); 20955c69072SChris Mason goto err; 21055c69072SChris Mason } 21155c69072SChris Mason if (eb->first_page != page) { 21255c69072SChris Mason printk("bad first page %lu %lu\n", eb->first_page->index, 21355c69072SChris Mason page->index); 21455c69072SChris Mason WARN_ON(1); 21555c69072SChris Mason goto err; 21655c69072SChris Mason } 21755c69072SChris Mason if (!PageUptodate(page)) { 21855c69072SChris Mason printk("csum not up to date page %lu\n", page->index); 21955c69072SChris Mason WARN_ON(1); 22055c69072SChris Mason goto err; 22119c00ddcSChris Mason } 22219c00ddcSChris Mason found_level = btrfs_header_level(eb); 22319c00ddcSChris Mason csum_tree_block(root, eb, 0); 22455c69072SChris Mason err: 22519c00ddcSChris Mason free_extent_buffer(eb); 22619c00ddcSChris Mason out: 22719c00ddcSChris Mason return 0; 22819c00ddcSChris Mason } 22919c00ddcSChris Mason 2300da5468fSChris Mason static int btree_writepage_io_hook(struct page *page, u64 start, u64 end) 2310da5468fSChris Mason { 2320da5468fSChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 2330da5468fSChris Mason 2340da5468fSChris Mason csum_dirty_buffer(root, page); 2350da5468fSChris Mason return 0; 2360da5468fSChris Mason } 2370da5468fSChris Mason 2380b86a832SChris Mason static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) 2390b86a832SChris Mason { 2400b86a832SChris Mason struct btrfs_root *root = BTRFS_I(inode)->root; 2410b86a832SChris Mason u64 offset; 2420b86a832SChris Mason offset = bio->bi_sector << 9; 2430b86a832SChris Mason if (offset == BTRFS_SUPER_INFO_OFFSET) { 2440b86a832SChris Mason bio->bi_bdev = root->fs_info->sb->s_bdev; 2450b86a832SChris Mason submit_bio(rw, bio); 2460b86a832SChris Mason return 0; 2470b86a832SChris Mason } 2480b86a832SChris Mason return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio); 2490b86a832SChris Mason } 2500b86a832SChris Mason 2515f39d397SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 2525f39d397SChris Mason { 253d1310b2eSChris Mason struct extent_io_tree *tree; 254d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 2555f39d397SChris Mason return extent_write_full_page(tree, page, btree_get_extent, wbc); 2565f39d397SChris Mason } 2570da5468fSChris Mason 2580da5468fSChris Mason static int btree_writepages(struct address_space *mapping, 2590da5468fSChris Mason struct writeback_control *wbc) 2600da5468fSChris Mason { 261d1310b2eSChris Mason struct extent_io_tree *tree; 262d1310b2eSChris Mason tree = &BTRFS_I(mapping->host)->io_tree; 263d8d5f3e1SChris Mason if (wbc->sync_mode == WB_SYNC_NONE) { 264793955bcSChris Mason u64 num_dirty; 265793955bcSChris Mason u64 start = 0; 266793955bcSChris Mason unsigned long thresh = 96 * 1024 * 1024; 267448d640bSChris Mason 268448d640bSChris Mason if (wbc->for_kupdate) 269448d640bSChris Mason return 0; 270448d640bSChris Mason 271ca664626SChris Mason if (current_is_pdflush()) { 272ca664626SChris Mason thresh = 96 * 1024 * 1024; 273ca664626SChris Mason } else { 274ca664626SChris Mason thresh = 8 * 1024 * 1024; 275ca664626SChris Mason } 2761832a6d5SChris Mason num_dirty = count_range_bits(tree, &start, (u64)-1, 2771832a6d5SChris Mason thresh, EXTENT_DIRTY); 278793955bcSChris Mason if (num_dirty < thresh) { 279793955bcSChris Mason return 0; 280793955bcSChris Mason } 281793955bcSChris Mason } 2820da5468fSChris Mason return extent_writepages(tree, mapping, btree_get_extent, wbc); 2830da5468fSChris Mason } 2840da5468fSChris Mason 2855f39d397SChris Mason int btree_readpage(struct file *file, struct page *page) 2865f39d397SChris Mason { 287d1310b2eSChris Mason struct extent_io_tree *tree; 288d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 2895f39d397SChris Mason return extent_read_full_page(tree, page, btree_get_extent); 2905f39d397SChris Mason } 2915f39d397SChris Mason 29270dec807SChris Mason static int btree_releasepage(struct page *page, gfp_t gfp_flags) 2935f39d397SChris Mason { 294d1310b2eSChris Mason struct extent_io_tree *tree; 295d1310b2eSChris Mason struct extent_map_tree *map; 2965f39d397SChris Mason int ret; 2975f39d397SChris Mason 298d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 299d1310b2eSChris Mason map = &BTRFS_I(page->mapping->host)->extent_tree; 30070dec807SChris Mason ret = try_release_extent_mapping(map, tree, page, gfp_flags); 3015f39d397SChris Mason if (ret == 1) { 3025f39d397SChris Mason ClearPagePrivate(page); 3035f39d397SChris Mason set_page_private(page, 0); 304d98237b3SChris Mason page_cache_release(page); 3055f39d397SChris Mason } 306d98237b3SChris Mason return ret; 307d98237b3SChris Mason } 308d98237b3SChris Mason 3095f39d397SChris Mason static void btree_invalidatepage(struct page *page, unsigned long offset) 310d98237b3SChris Mason { 311d1310b2eSChris Mason struct extent_io_tree *tree; 312d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 3135f39d397SChris Mason extent_invalidatepage(tree, page, offset); 3145f39d397SChris Mason btree_releasepage(page, GFP_NOFS); 315d98237b3SChris Mason } 316d98237b3SChris Mason 3175f39d397SChris Mason #if 0 318d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 319d98237b3SChris Mason { 32087cbda5cSChris Mason struct buffer_head *bh; 3210f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 32287cbda5cSChris Mason struct buffer_head *head; 32387cbda5cSChris Mason if (!page_has_buffers(page)) { 32487cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 32587cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 32687cbda5cSChris Mason } 32787cbda5cSChris Mason head = page_buffers(page); 32887cbda5cSChris Mason bh = head; 32987cbda5cSChris Mason do { 33087cbda5cSChris Mason if (buffer_dirty(bh)) 33187cbda5cSChris Mason csum_tree_block(root, bh, 0); 33287cbda5cSChris Mason bh = bh->b_this_page; 33387cbda5cSChris Mason } while (bh != head); 334d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 335d98237b3SChris Mason } 3365f39d397SChris Mason #endif 337d98237b3SChris Mason 338d98237b3SChris Mason static struct address_space_operations btree_aops = { 339d98237b3SChris Mason .readpage = btree_readpage, 340d98237b3SChris Mason .writepage = btree_writepage, 3410da5468fSChris Mason .writepages = btree_writepages, 3425f39d397SChris Mason .releasepage = btree_releasepage, 3435f39d397SChris Mason .invalidatepage = btree_invalidatepage, 344d98237b3SChris Mason .sync_page = block_sync_page, 345d98237b3SChris Mason }; 346123abc88SChris Mason 347db94535dSChris Mason int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) 348090d1875SChris Mason { 3495f39d397SChris Mason struct extent_buffer *buf = NULL; 3505f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 351de428b63SChris Mason int ret = 0; 352090d1875SChris Mason 353db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3545f39d397SChris Mason if (!buf) 355090d1875SChris Mason return 0; 356d1310b2eSChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 357a86c12c7SChris Mason buf, 0, 0, btree_get_extent); 3585f39d397SChris Mason free_extent_buffer(buf); 359de428b63SChris Mason return ret; 360090d1875SChris Mason } 361090d1875SChris Mason 3620b86a832SChris Mason static int close_all_devices(struct btrfs_fs_info *fs_info) 3630b86a832SChris Mason { 3640b86a832SChris Mason struct list_head *list; 3650b86a832SChris Mason struct list_head *next; 3660b86a832SChris Mason struct btrfs_device *device; 3670b86a832SChris Mason 3680b86a832SChris Mason list = &fs_info->devices; 3690b86a832SChris Mason while(!list_empty(list)) { 3700b86a832SChris Mason next = list->next; 3710b86a832SChris Mason list_del(next); 3720b86a832SChris Mason device = list_entry(next, struct btrfs_device, dev_list); 3730b86a832SChris Mason kfree(device->name); 3740b86a832SChris Mason kfree(device); 3750b86a832SChris Mason } 3760b86a832SChris Mason return 0; 3770b86a832SChris Mason } 3780b86a832SChris Mason 379db94535dSChris Mason struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 380db94535dSChris Mason u32 blocksize) 381e20d96d6SChris Mason { 3825f39d397SChris Mason struct extent_buffer *buf = NULL; 3835f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 384d1310b2eSChris Mason struct extent_io_tree *io_tree; 385e4204dedSChris Mason u64 end; 38619c00ddcSChris Mason int ret; 38719c00ddcSChris Mason 388d1310b2eSChris Mason io_tree = &BTRFS_I(btree_inode)->io_tree; 389e20d96d6SChris Mason 390db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 3915f39d397SChris Mason if (!buf) 392d98237b3SChris Mason return NULL; 393a86c12c7SChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1, 394a86c12c7SChris Mason btree_get_extent); 395e4204dedSChris Mason 396e4204dedSChris Mason if (buf->flags & EXTENT_CSUM) 39719c00ddcSChris Mason return buf; 398e4204dedSChris Mason 399e4204dedSChris Mason end = buf->start + PAGE_CACHE_SIZE - 1; 400d1310b2eSChris Mason if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { 40119c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 40219c00ddcSChris Mason return buf; 40319c00ddcSChris Mason } 404e4204dedSChris Mason 405d1310b2eSChris Mason lock_extent(io_tree, buf->start, end, GFP_NOFS); 406e4204dedSChris Mason 407d1310b2eSChris Mason if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { 408e4204dedSChris Mason buf->flags |= EXTENT_CSUM; 409e4204dedSChris Mason goto out_unlock; 410e4204dedSChris Mason } 411e4204dedSChris Mason 41219c00ddcSChris Mason ret = csum_tree_block(root, buf, 1); 413d1310b2eSChris Mason set_extent_bits(io_tree, buf->start, end, EXTENT_CSUM, GFP_NOFS); 41419c00ddcSChris Mason buf->flags |= EXTENT_CSUM; 415e4204dedSChris Mason 416e4204dedSChris Mason out_unlock: 417d1310b2eSChris Mason unlock_extent(io_tree, buf->start, end, GFP_NOFS); 4185f39d397SChris Mason return buf; 419eb60ceacSChris Mason } 420eb60ceacSChris Mason 421e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 4225f39d397SChris Mason struct extent_buffer *buf) 423ed2ff2cbSChris Mason { 4245f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 42555c69072SChris Mason if (btrfs_header_generation(buf) == 42655c69072SChris Mason root->fs_info->running_transaction->transid) 427d1310b2eSChris Mason clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, 42855c69072SChris Mason buf); 4295f39d397SChris Mason return 0; 4305f39d397SChris Mason } 4315f39d397SChris Mason 4325f39d397SChris Mason int wait_on_tree_block_writeback(struct btrfs_root *root, 4335f39d397SChris Mason struct extent_buffer *buf) 4345f39d397SChris Mason { 4355f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 436d1310b2eSChris Mason wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->io_tree, 4375f39d397SChris Mason buf); 4385f39d397SChris Mason return 0; 4395f39d397SChris Mason } 4405f39d397SChris Mason 441db94535dSChris Mason static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 44287ee04ebSChris Mason u32 stripesize, struct btrfs_root *root, 4439f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 444e20d96d6SChris Mason u64 objectid) 445d97e63b6SChris Mason { 446cfaa7295SChris Mason root->node = NULL; 4470f7d52f4SChris Mason root->inode = NULL; 448a28ec197SChris Mason root->commit_root = NULL; 449db94535dSChris Mason root->sectorsize = sectorsize; 450db94535dSChris Mason root->nodesize = nodesize; 451db94535dSChris Mason root->leafsize = leafsize; 45287ee04ebSChris Mason root->stripesize = stripesize; 453123abc88SChris Mason root->ref_cows = 0; 4540b86a832SChris Mason root->track_dirty = 0; 4550b86a832SChris Mason 4569f5fae2fSChris Mason root->fs_info = fs_info; 4570f7d52f4SChris Mason root->objectid = objectid; 4580f7d52f4SChris Mason root->last_trans = 0; 4591b05da2eSChris Mason root->highest_inode = 0; 4601b05da2eSChris Mason root->last_inode_alloc = 0; 46158176a96SJosef Bacik root->name = NULL; 4624313b399SChris Mason root->in_sysfs = 0; 4630b86a832SChris Mason 4640b86a832SChris Mason INIT_LIST_HEAD(&root->dirty_list); 4653768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 4663768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 4676702ed49SChris Mason memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 46858176a96SJosef Bacik memset(&root->root_kobj, 0, sizeof(root->root_kobj)); 46958176a96SJosef Bacik init_completion(&root->kobj_unregister); 4706702ed49SChris Mason root->defrag_running = 0; 4716702ed49SChris Mason root->defrag_level = 0; 4724d775673SChris Mason root->root_key.objectid = objectid; 4733768f368SChris Mason return 0; 4743768f368SChris Mason } 4753768f368SChris Mason 476db94535dSChris Mason static int find_and_setup_root(struct btrfs_root *tree_root, 4779f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 4789f5fae2fSChris Mason u64 objectid, 479e20d96d6SChris Mason struct btrfs_root *root) 4803768f368SChris Mason { 4813768f368SChris Mason int ret; 482db94535dSChris Mason u32 blocksize; 4833768f368SChris Mason 484db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 48587ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 48687ee04ebSChris Mason root, fs_info, objectid); 4873768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 4883768f368SChris Mason &root->root_item, &root->root_key); 4893768f368SChris Mason BUG_ON(ret); 4903768f368SChris Mason 491db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 492db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 493db94535dSChris Mason blocksize); 4943768f368SChris Mason BUG_ON(!root->node); 495d97e63b6SChris Mason return 0; 496d97e63b6SChris Mason } 497d97e63b6SChris Mason 4985eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 4990f7d52f4SChris Mason struct btrfs_key *location) 5000f7d52f4SChris Mason { 5010f7d52f4SChris Mason struct btrfs_root *root; 5020f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 5030f7d52f4SChris Mason struct btrfs_path *path; 5045f39d397SChris Mason struct extent_buffer *l; 5051b05da2eSChris Mason u64 highest_inode; 506db94535dSChris Mason u32 blocksize; 5070f7d52f4SChris Mason int ret = 0; 5080f7d52f4SChris Mason 5095eda7b5eSChris Mason root = kzalloc(sizeof(*root), GFP_NOFS); 5100cf6c620SChris Mason if (!root) 5110f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 5120f7d52f4SChris Mason if (location->offset == (u64)-1) { 513db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 5140f7d52f4SChris Mason location->objectid, root); 5150f7d52f4SChris Mason if (ret) { 5160f7d52f4SChris Mason kfree(root); 5170f7d52f4SChris Mason return ERR_PTR(ret); 5180f7d52f4SChris Mason } 5190f7d52f4SChris Mason goto insert; 5200f7d52f4SChris Mason } 5210f7d52f4SChris Mason 522db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 52387ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 52487ee04ebSChris Mason root, fs_info, location->objectid); 5250f7d52f4SChris Mason 5260f7d52f4SChris Mason path = btrfs_alloc_path(); 5270f7d52f4SChris Mason BUG_ON(!path); 5280f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 5290f7d52f4SChris Mason if (ret != 0) { 5300f7d52f4SChris Mason if (ret > 0) 5310f7d52f4SChris Mason ret = -ENOENT; 5320f7d52f4SChris Mason goto out; 5330f7d52f4SChris Mason } 5345f39d397SChris Mason l = path->nodes[0]; 5355f39d397SChris Mason read_extent_buffer(l, &root->root_item, 5365f39d397SChris Mason btrfs_item_ptr_offset(l, path->slots[0]), 5370f7d52f4SChris Mason sizeof(root->root_item)); 53844b36eb2SYan Zheng memcpy(&root->root_key, location, sizeof(*location)); 5390f7d52f4SChris Mason ret = 0; 5400f7d52f4SChris Mason out: 5410f7d52f4SChris Mason btrfs_release_path(root, path); 5420f7d52f4SChris Mason btrfs_free_path(path); 5430f7d52f4SChris Mason if (ret) { 5440f7d52f4SChris Mason kfree(root); 5450f7d52f4SChris Mason return ERR_PTR(ret); 5460f7d52f4SChris Mason } 547db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 548db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 549db94535dSChris Mason blocksize); 5500f7d52f4SChris Mason BUG_ON(!root->node); 5510f7d52f4SChris Mason insert: 5520f7d52f4SChris Mason root->ref_cows = 1; 5535eda7b5eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 5545eda7b5eSChris Mason if (ret == 0) { 5555eda7b5eSChris Mason root->highest_inode = highest_inode; 5565eda7b5eSChris Mason root->last_inode_alloc = highest_inode; 5575eda7b5eSChris Mason } 5585eda7b5eSChris Mason return root; 5595eda7b5eSChris Mason } 5605eda7b5eSChris Mason 561dc17ff8fSChris Mason struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, 562dc17ff8fSChris Mason u64 root_objectid) 563dc17ff8fSChris Mason { 564dc17ff8fSChris Mason struct btrfs_root *root; 565dc17ff8fSChris Mason 566dc17ff8fSChris Mason if (root_objectid == BTRFS_ROOT_TREE_OBJECTID) 567dc17ff8fSChris Mason return fs_info->tree_root; 568dc17ff8fSChris Mason if (root_objectid == BTRFS_EXTENT_TREE_OBJECTID) 569dc17ff8fSChris Mason return fs_info->extent_root; 570dc17ff8fSChris Mason 571dc17ff8fSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 572dc17ff8fSChris Mason (unsigned long)root_objectid); 573dc17ff8fSChris Mason return root; 574dc17ff8fSChris Mason } 575dc17ff8fSChris Mason 576edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, 577edbd8d4eSChris Mason struct btrfs_key *location) 5785eda7b5eSChris Mason { 5795eda7b5eSChris Mason struct btrfs_root *root; 5805eda7b5eSChris Mason int ret; 5815eda7b5eSChris Mason 582edbd8d4eSChris Mason if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) 583edbd8d4eSChris Mason return fs_info->tree_root; 584edbd8d4eSChris Mason if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) 585edbd8d4eSChris Mason return fs_info->extent_root; 586edbd8d4eSChris Mason 5875eda7b5eSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 5885eda7b5eSChris Mason (unsigned long)location->objectid); 5895eda7b5eSChris Mason if (root) 5905eda7b5eSChris Mason return root; 5915eda7b5eSChris Mason 5925eda7b5eSChris Mason root = btrfs_read_fs_root_no_radix(fs_info, location); 5935eda7b5eSChris Mason if (IS_ERR(root)) 5945eda7b5eSChris Mason return root; 5952619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 5962619ba1fSChris Mason (unsigned long)root->root_key.objectid, 5970f7d52f4SChris Mason root); 5980f7d52f4SChris Mason if (ret) { 5995f39d397SChris Mason free_extent_buffer(root->node); 6000f7d52f4SChris Mason kfree(root); 6010f7d52f4SChris Mason return ERR_PTR(ret); 6020f7d52f4SChris Mason } 603edbd8d4eSChris Mason ret = btrfs_find_dead_roots(fs_info->tree_root, 604edbd8d4eSChris Mason root->root_key.objectid, root); 605edbd8d4eSChris Mason BUG_ON(ret); 606edbd8d4eSChris Mason 607edbd8d4eSChris Mason return root; 608edbd8d4eSChris Mason } 609edbd8d4eSChris Mason 610edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 611edbd8d4eSChris Mason struct btrfs_key *location, 612edbd8d4eSChris Mason const char *name, int namelen) 613edbd8d4eSChris Mason { 614edbd8d4eSChris Mason struct btrfs_root *root; 615edbd8d4eSChris Mason int ret; 616edbd8d4eSChris Mason 617edbd8d4eSChris Mason root = btrfs_read_fs_root_no_name(fs_info, location); 618edbd8d4eSChris Mason if (!root) 619edbd8d4eSChris Mason return NULL; 62058176a96SJosef Bacik 6214313b399SChris Mason if (root->in_sysfs) 6224313b399SChris Mason return root; 6234313b399SChris Mason 62458176a96SJosef Bacik ret = btrfs_set_root_name(root, name, namelen); 62558176a96SJosef Bacik if (ret) { 6265f39d397SChris Mason free_extent_buffer(root->node); 62758176a96SJosef Bacik kfree(root); 62858176a96SJosef Bacik return ERR_PTR(ret); 62958176a96SJosef Bacik } 63058176a96SJosef Bacik 63158176a96SJosef Bacik ret = btrfs_sysfs_add_root(root); 63258176a96SJosef Bacik if (ret) { 6335f39d397SChris Mason free_extent_buffer(root->node); 63458176a96SJosef Bacik kfree(root->name); 63558176a96SJosef Bacik kfree(root); 63658176a96SJosef Bacik return ERR_PTR(ret); 63758176a96SJosef Bacik } 6384313b399SChris Mason root->in_sysfs = 1; 6390f7d52f4SChris Mason return root; 6400f7d52f4SChris Mason } 64119c00ddcSChris Mason #if 0 64219c00ddcSChris Mason static int add_hasher(struct btrfs_fs_info *info, char *type) { 64319c00ddcSChris Mason struct btrfs_hasher *hasher; 6440f7d52f4SChris Mason 64519c00ddcSChris Mason hasher = kmalloc(sizeof(*hasher), GFP_NOFS); 64619c00ddcSChris Mason if (!hasher) 64719c00ddcSChris Mason return -ENOMEM; 64819c00ddcSChris Mason hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC); 64919c00ddcSChris Mason if (!hasher->hash_tfm) { 65019c00ddcSChris Mason kfree(hasher); 65119c00ddcSChris Mason return -EINVAL; 65219c00ddcSChris Mason } 65319c00ddcSChris Mason spin_lock(&info->hash_lock); 65419c00ddcSChris Mason list_add(&hasher->list, &info->hashers); 65519c00ddcSChris Mason spin_unlock(&info->hash_lock); 65619c00ddcSChris Mason return 0; 65719c00ddcSChris Mason } 65819c00ddcSChris Mason #endif 6592c90e5d6SChris Mason struct btrfs_root *open_ctree(struct super_block *sb) 660eb60ceacSChris Mason { 661db94535dSChris Mason u32 sectorsize; 662db94535dSChris Mason u32 nodesize; 663db94535dSChris Mason u32 leafsize; 664db94535dSChris Mason u32 blocksize; 66587ee04ebSChris Mason u32 stripesize; 666e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 667e20d96d6SChris Mason GFP_NOFS); 668e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 669e20d96d6SChris Mason GFP_NOFS); 670e20d96d6SChris Mason struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 671e20d96d6SChris Mason GFP_NOFS); 6720b86a832SChris Mason struct btrfs_root *chunk_root = kmalloc(sizeof(struct btrfs_root), 6730b86a832SChris Mason GFP_NOFS); 6740b86a832SChris Mason struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root), 6750b86a832SChris Mason GFP_NOFS); 676eb60ceacSChris Mason int ret; 67739279cc3SChris Mason int err = -EIO; 6782c90e5d6SChris Mason struct btrfs_super_block *disk_super; 679eb60ceacSChris Mason 68039279cc3SChris Mason if (!extent_root || !tree_root || !fs_info) { 68139279cc3SChris Mason err = -ENOMEM; 68239279cc3SChris Mason goto fail; 68339279cc3SChris Mason } 6840f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 6858fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 686facda1e7SChris Mason INIT_LIST_HEAD(&fs_info->dead_roots); 68719c00ddcSChris Mason INIT_LIST_HEAD(&fs_info->hashers); 68819c00ddcSChris Mason spin_lock_init(&fs_info->hash_lock); 6891832a6d5SChris Mason spin_lock_init(&fs_info->delalloc_lock); 690cee36a03SChris Mason spin_lock_init(&fs_info->new_trans_lock); 69119c00ddcSChris Mason 69258176a96SJosef Bacik memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj)); 69358176a96SJosef Bacik init_completion(&fs_info->kobj_unregister); 6942c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 6959f5fae2fSChris Mason fs_info->running_transaction = NULL; 69615ee9bc7SJosef Bacik fs_info->last_trans_committed = 0; 6979f5fae2fSChris Mason fs_info->tree_root = tree_root; 6989f5fae2fSChris Mason fs_info->extent_root = extent_root; 6990b86a832SChris Mason fs_info->chunk_root = chunk_root; 7000b86a832SChris Mason fs_info->dev_root = dev_root; 7010b86a832SChris Mason INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); 7020b86a832SChris Mason INIT_LIST_HEAD(&fs_info->devices); 7036324fbf3SChris Mason INIT_LIST_HEAD(&fs_info->space_info); 7040b86a832SChris Mason btrfs_mapping_init(&fs_info->mapping_tree); 705e20d96d6SChris Mason fs_info->sb = sb; 706e2008b61SChris Mason fs_info->throttles = 0; 707b6cda9bcSChris Mason fs_info->mount_opt = 0; 708c59f8951SChris Mason fs_info->max_extent = (u64)-1; 7096f568d35SChris Mason fs_info->max_inline = 8192 * 1024; 7101832a6d5SChris Mason fs_info->delalloc_bytes = 0; 711d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 712d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 7132c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 714d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 715d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 716d1310b2eSChris Mason extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree, 7175f39d397SChris Mason fs_info->btree_inode->i_mapping, 7185f39d397SChris Mason GFP_NOFS); 719d1310b2eSChris Mason extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, 720d1310b2eSChris Mason GFP_NOFS); 7210da5468fSChris Mason 722d1310b2eSChris Mason BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; 723d1310b2eSChris Mason 724d1310b2eSChris Mason extent_io_tree_init(&fs_info->free_space_cache, 725f510cfecSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 726d1310b2eSChris Mason extent_io_tree_init(&fs_info->block_group_cache, 72796b5179dSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 728d1310b2eSChris Mason extent_io_tree_init(&fs_info->pinned_extents, 7291a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 730d1310b2eSChris Mason extent_io_tree_init(&fs_info->pending_del, 7311a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 732d1310b2eSChris Mason extent_io_tree_init(&fs_info->extent_ins, 7331a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 734e66f709bSChris Mason fs_info->do_barriers = 1; 735facda1e7SChris Mason fs_info->closing = 0; 736324ae4dfSYan fs_info->total_pinned = 0; 737e18e4809SChris Mason fs_info->last_alloc = 0; 7384529ba49SChris Mason fs_info->last_data_alloc = 0; 739e18e4809SChris Mason 7406da6abaeSChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 7416da6abaeSChris Mason INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); 7426da6abaeSChris Mason #else 74308607c1bSChris Mason INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 7446da6abaeSChris Mason #endif 7450f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 7460f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 7470f7d52f4SChris Mason sizeof(struct btrfs_key)); 74822b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 749d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 75039279cc3SChris Mason 75179154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 752d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 7533768f368SChris Mason 75419c00ddcSChris Mason #if 0 75519c00ddcSChris Mason ret = add_hasher(fs_info, "crc32c"); 75619c00ddcSChris Mason if (ret) { 75719c00ddcSChris Mason printk("btrfs: failed hash setup, modprobe cryptomgr?\n"); 75819c00ddcSChris Mason err = -ENOMEM; 75919c00ddcSChris Mason goto fail_iput; 76019c00ddcSChris Mason } 76119c00ddcSChris Mason #endif 7620b86a832SChris Mason __setup_root(4096, 4096, 4096, 4096, tree_root, 7632c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 7647eccb903SChris Mason 7652c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 766db94535dSChris Mason BTRFS_SUPER_INFO_OFFSET, 7670b86a832SChris Mason 4096); 768d98237b3SChris Mason 7690f7d52f4SChris Mason if (!fs_info->sb_buffer) 77039279cc3SChris Mason goto fail_iput; 77139279cc3SChris Mason 7725f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, 7735f39d397SChris Mason sizeof(fs_info->super_copy)); 7745f39d397SChris Mason 7755f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, 7765f39d397SChris Mason (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), 7775f39d397SChris Mason BTRFS_FSID_SIZE); 7780b86a832SChris Mason 7795f39d397SChris Mason disk_super = &fs_info->super_copy; 7800f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 78139279cc3SChris Mason goto fail_sb_buffer; 7820f7d52f4SChris Mason 783db94535dSChris Mason nodesize = btrfs_super_nodesize(disk_super); 784db94535dSChris Mason leafsize = btrfs_super_leafsize(disk_super); 785db94535dSChris Mason sectorsize = btrfs_super_sectorsize(disk_super); 78687ee04ebSChris Mason stripesize = btrfs_super_stripesize(disk_super); 787db94535dSChris Mason tree_root->nodesize = nodesize; 788db94535dSChris Mason tree_root->leafsize = leafsize; 789db94535dSChris Mason tree_root->sectorsize = sectorsize; 79087ee04ebSChris Mason tree_root->stripesize = stripesize; 791ff79f819SChris Mason sb_set_blocksize(sb, sectorsize); 792db94535dSChris Mason 7938352d8a4SChris Mason i_size_write(fs_info->btree_inode, 794db94535dSChris Mason btrfs_super_total_bytes(disk_super)); 7958352d8a4SChris Mason 79639279cc3SChris Mason if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 79739279cc3SChris Mason sizeof(disk_super->magic))) { 79839279cc3SChris Mason printk("btrfs: valid FS not found on %s\n", sb->s_id); 79939279cc3SChris Mason goto fail_sb_buffer; 80039279cc3SChris Mason } 80119c00ddcSChris Mason 8020b86a832SChris Mason mutex_lock(&fs_info->fs_mutex); 8030b86a832SChris Mason ret = btrfs_read_sys_array(tree_root); 8040b86a832SChris Mason BUG_ON(ret); 8050b86a832SChris Mason 8060b86a832SChris Mason blocksize = btrfs_level_size(tree_root, 8070b86a832SChris Mason btrfs_super_chunk_root_level(disk_super)); 8080b86a832SChris Mason 8090b86a832SChris Mason __setup_root(nodesize, leafsize, sectorsize, stripesize, 8100b86a832SChris Mason chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); 8110b86a832SChris Mason 8120b86a832SChris Mason chunk_root->node = read_tree_block(chunk_root, 8130b86a832SChris Mason btrfs_super_chunk_root(disk_super), 8140b86a832SChris Mason blocksize); 8150b86a832SChris Mason BUG_ON(!chunk_root->node); 8160b86a832SChris Mason 8170b86a832SChris Mason ret = btrfs_read_chunk_tree(chunk_root); 8180b86a832SChris Mason BUG_ON(ret); 8190b86a832SChris Mason 820db94535dSChris Mason blocksize = btrfs_level_size(tree_root, 821db94535dSChris Mason btrfs_super_root_level(disk_super)); 82219c00ddcSChris Mason 8230b86a832SChris Mason 824e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 825db94535dSChris Mason btrfs_super_root(disk_super), 826db94535dSChris Mason blocksize); 82739279cc3SChris Mason if (!tree_root->node) 82839279cc3SChris Mason goto fail_sb_buffer; 8293768f368SChris Mason 830db94535dSChris Mason 831db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 832e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 8330b86a832SChris Mason if (ret) 83439279cc3SChris Mason goto fail_tree_root; 8350b86a832SChris Mason extent_root->track_dirty = 1; 8360b86a832SChris Mason 8370b86a832SChris Mason ret = find_and_setup_root(tree_root, fs_info, 8380b86a832SChris Mason BTRFS_DEV_TREE_OBJECTID, dev_root); 8390b86a832SChris Mason dev_root->track_dirty = 1; 8400b86a832SChris Mason 8410b86a832SChris Mason if (ret) 8420b86a832SChris Mason goto fail_extent_root; 8433768f368SChris Mason 8449078a3e1SChris Mason btrfs_read_block_groups(extent_root); 8459078a3e1SChris Mason 8460f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 8475be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 8480f7d52f4SChris Mason return tree_root; 84939279cc3SChris Mason 8500b86a832SChris Mason fail_extent_root: 8510b86a832SChris Mason free_extent_buffer(extent_root->node); 85239279cc3SChris Mason fail_tree_root: 8530b86a832SChris Mason mutex_unlock(&fs_info->fs_mutex); 8545f39d397SChris Mason free_extent_buffer(tree_root->node); 85539279cc3SChris Mason fail_sb_buffer: 8565f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 85739279cc3SChris Mason fail_iput: 85839279cc3SChris Mason iput(fs_info->btree_inode); 85939279cc3SChris Mason fail: 86039279cc3SChris Mason kfree(extent_root); 86139279cc3SChris Mason kfree(tree_root); 86239279cc3SChris Mason kfree(fs_info); 86339279cc3SChris Mason return ERR_PTR(err); 864eb60ceacSChris Mason } 865eb60ceacSChris Mason 866e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 86779154b1bSChris Mason *root) 868cfaa7295SChris Mason { 869e66f709bSChris Mason int ret; 8705f39d397SChris Mason struct extent_buffer *super = root->fs_info->sb_buffer; 8715f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 87221ad10cfSChris Mason struct super_block *sb = root->fs_info->sb; 8732c90e5d6SChris Mason 87421ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 87521ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 876d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super); 8775f39d397SChris Mason ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, 8785f39d397SChris Mason super->start, super->len); 87921ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 88021ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 8815f39d397SChris Mason return ret; 882cfaa7295SChris Mason } 883cfaa7295SChris Mason 8845eda7b5eSChris Mason int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 8852619ba1fSChris Mason { 8862619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 8872619ba1fSChris Mason (unsigned long)root->root_key.objectid); 888b99aa6cbSChris Mason if (root->in_sysfs) 88958176a96SJosef Bacik btrfs_sysfs_del_root(root); 8902619ba1fSChris Mason if (root->inode) 8912619ba1fSChris Mason iput(root->inode); 8922619ba1fSChris Mason if (root->node) 8935f39d397SChris Mason free_extent_buffer(root->node); 8942619ba1fSChris Mason if (root->commit_root) 8955f39d397SChris Mason free_extent_buffer(root->commit_root); 89658176a96SJosef Bacik if (root->name) 89758176a96SJosef Bacik kfree(root->name); 8982619ba1fSChris Mason kfree(root); 8992619ba1fSChris Mason return 0; 9002619ba1fSChris Mason } 9012619ba1fSChris Mason 90235b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 9030f7d52f4SChris Mason { 9040f7d52f4SChris Mason int ret; 9050f7d52f4SChris Mason struct btrfs_root *gang[8]; 9060f7d52f4SChris Mason int i; 9070f7d52f4SChris Mason 9080f7d52f4SChris Mason while(1) { 9090f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 9100f7d52f4SChris Mason (void **)gang, 0, 9110f7d52f4SChris Mason ARRAY_SIZE(gang)); 9120f7d52f4SChris Mason if (!ret) 9130f7d52f4SChris Mason break; 9142619ba1fSChris Mason for (i = 0; i < ret; i++) 9155eda7b5eSChris Mason btrfs_free_fs_root(fs_info, gang[i]); 9160f7d52f4SChris Mason } 9170f7d52f4SChris Mason return 0; 9180f7d52f4SChris Mason } 919b4100d64SChris Mason 920e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 921eb60ceacSChris Mason { 9223768f368SChris Mason int ret; 923e089f05cSChris Mason struct btrfs_trans_handle *trans; 9240f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 925e089f05cSChris Mason 926facda1e7SChris Mason fs_info->closing = 1; 92708607c1bSChris Mason btrfs_transaction_flush_work(root); 9280f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 9296702ed49SChris Mason btrfs_defrag_dirty_roots(root->fs_info); 93079154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 93154aa1f4dSChris Mason ret = btrfs_commit_transaction(trans, root); 93279154b1bSChris Mason /* run commit again to drop the original snapshot */ 93379154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 93479154b1bSChris Mason btrfs_commit_transaction(trans, root); 93579154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 9369f5fae2fSChris Mason BUG_ON(ret); 93779154b1bSChris Mason write_ctree_super(NULL, root); 9380f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 939ed2ff2cbSChris Mason 940b0c68f8bSChris Mason if (fs_info->delalloc_bytes) { 941b0c68f8bSChris Mason printk("btrfs: at unmount delalloc count %Lu\n", 942b0c68f8bSChris Mason fs_info->delalloc_bytes); 943b0c68f8bSChris Mason } 9440f7d52f4SChris Mason if (fs_info->extent_root->node) 9455f39d397SChris Mason free_extent_buffer(fs_info->extent_root->node); 946f510cfecSChris Mason 9470f7d52f4SChris Mason if (fs_info->tree_root->node) 9485f39d397SChris Mason free_extent_buffer(fs_info->tree_root->node); 949f510cfecSChris Mason 9500b86a832SChris Mason if (root->fs_info->chunk_root->node); 9510b86a832SChris Mason free_extent_buffer(root->fs_info->chunk_root->node); 9520b86a832SChris Mason 9530b86a832SChris Mason if (root->fs_info->dev_root->node); 9540b86a832SChris Mason free_extent_buffer(root->fs_info->dev_root->node); 9550b86a832SChris Mason 9565f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 9577eccb903SChris Mason 9589078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 9590f7d52f4SChris Mason del_fs_roots(fs_info); 960d10c5f31SChris Mason 961d10c5f31SChris Mason filemap_write_and_wait(fs_info->btree_inode->i_mapping); 962d10c5f31SChris Mason 963d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->free_space_cache); 964d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->block_group_cache); 965d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pinned_extents); 966d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pending_del); 967d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->extent_ins); 968d1310b2eSChris Mason extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); 969d10c5f31SChris Mason 970db94535dSChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 971d10c5f31SChris Mason 972db94535dSChris Mason iput(fs_info->btree_inode); 97319c00ddcSChris Mason #if 0 97419c00ddcSChris Mason while(!list_empty(&fs_info->hashers)) { 97519c00ddcSChris Mason struct btrfs_hasher *hasher; 97619c00ddcSChris Mason hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher, 97719c00ddcSChris Mason hashers); 97819c00ddcSChris Mason list_del(&hasher->hashers); 97919c00ddcSChris Mason crypto_free_hash(&fs_info->hash_tfm); 98019c00ddcSChris Mason kfree(hasher); 98119c00ddcSChris Mason } 98219c00ddcSChris Mason #endif 9830b86a832SChris Mason close_all_devices(fs_info); 9840b86a832SChris Mason btrfs_mapping_tree_free(&fs_info->mapping_tree); 9850b86a832SChris Mason 9860f7d52f4SChris Mason kfree(fs_info->extent_root); 9870f7d52f4SChris Mason kfree(fs_info->tree_root); 9880b86a832SChris Mason kfree(fs_info->chunk_root); 9890b86a832SChris Mason kfree(fs_info->dev_root); 990eb60ceacSChris Mason return 0; 991eb60ceacSChris Mason } 992eb60ceacSChris Mason 9935f39d397SChris Mason int btrfs_buffer_uptodate(struct extent_buffer *buf) 994ccd467d6SChris Mason { 995810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 996d1310b2eSChris Mason return extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); 9975f39d397SChris Mason } 9986702ed49SChris Mason 9995f39d397SChris Mason int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 10005f39d397SChris Mason { 1001810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 1002d1310b2eSChris Mason return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, 10035f39d397SChris Mason buf); 10045f39d397SChris Mason } 10055f39d397SChris Mason 10065f39d397SChris Mason void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 10075f39d397SChris Mason { 1008810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10095f39d397SChris Mason u64 transid = btrfs_header_generation(buf); 10105f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 10116702ed49SChris Mason 1012ccd467d6SChris Mason if (transid != root->fs_info->generation) { 1013ccd467d6SChris Mason printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 1014db94535dSChris Mason (unsigned long long)buf->start, 1015ccd467d6SChris Mason transid, root->fs_info->generation); 1016ccd467d6SChris Mason WARN_ON(1); 1017ccd467d6SChris Mason } 1018d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); 1019eb60ceacSChris Mason } 1020eb60ceacSChris Mason 1021e2008b61SChris Mason void btrfs_throttle(struct btrfs_root *root) 1022e2008b61SChris Mason { 102355c69072SChris Mason struct backing_dev_info *bdi; 102455c69072SChris Mason 102555c69072SChris Mason bdi = root->fs_info->sb->s_bdev->bd_inode->i_mapping->backing_dev_info; 102604005cc7SChris Mason if (root->fs_info->throttles && bdi_write_congested(bdi)) { 102704005cc7SChris Mason #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) 102855c69072SChris Mason congestion_wait(WRITE, HZ/20); 102904005cc7SChris Mason #else 103004005cc7SChris Mason blk_congestion_wait(WRITE, HZ/20); 103104005cc7SChris Mason #endif 103204005cc7SChris Mason } 1033e2008b61SChris Mason } 1034e2008b61SChris Mason 1035d3c2fdcfSChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) 103635b7e476SChris Mason { 1037d3c2fdcfSChris Mason balance_dirty_pages_ratelimited_nr( 1038304fced6SChris Mason root->fs_info->btree_inode->i_mapping, 1); 103935b7e476SChris Mason } 10406b80053dSChris Mason 10416b80053dSChris Mason void btrfs_set_buffer_defrag(struct extent_buffer *buf) 10426b80053dSChris Mason { 1043810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10446b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1045d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 10466b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 10476b80053dSChris Mason } 10486b80053dSChris Mason 10496b80053dSChris Mason void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 10506b80053dSChris Mason { 1051810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10526b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1053d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 10546b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 10556b80053dSChris Mason GFP_NOFS); 10566b80053dSChris Mason } 10576b80053dSChris Mason 10586b80053dSChris Mason int btrfs_buffer_defrag(struct extent_buffer *buf) 10596b80053dSChris Mason { 1060810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10616b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1062d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 10636b80053dSChris Mason buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 10646b80053dSChris Mason } 10656b80053dSChris Mason 10666b80053dSChris Mason int btrfs_buffer_defrag_done(struct extent_buffer *buf) 10676b80053dSChris Mason { 1068810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10696b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1070d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 10716b80053dSChris Mason buf->start, buf->start + buf->len - 1, 10726b80053dSChris Mason EXTENT_DEFRAG_DONE, 0); 10736b80053dSChris Mason } 10746b80053dSChris Mason 10756b80053dSChris Mason int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 10766b80053dSChris Mason { 1077810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10786b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1079d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 10806b80053dSChris Mason buf->start, buf->start + buf->len - 1, 10816b80053dSChris Mason EXTENT_DEFRAG_DONE, GFP_NOFS); 10826b80053dSChris Mason } 10836b80053dSChris Mason 10846b80053dSChris Mason int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 10856b80053dSChris Mason { 1086810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10876b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1088d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 10896b80053dSChris Mason buf->start, buf->start + buf->len - 1, 10906b80053dSChris Mason EXTENT_DEFRAG, GFP_NOFS); 10916b80053dSChris Mason } 10926b80053dSChris Mason 10936b80053dSChris Mason int btrfs_read_buffer(struct extent_buffer *buf) 10946b80053dSChris Mason { 1095810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 10966b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1097d1310b2eSChris Mason return read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 1098a86c12c7SChris Mason buf, 0, 1, btree_get_extent); 10996b80053dSChris Mason } 11000da5468fSChris Mason 1101d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops = { 11020da5468fSChris Mason .writepage_io_hook = btree_writepage_io_hook, 11030b86a832SChris Mason .submit_bio_hook = btree_submit_bio_hook, 11040da5468fSChris Mason }; 1105