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 27ce9adaa5SChris Mason #include <linux/workqueue.h> 28eb60ceacSChris Mason #include "ctree.h" 29eb60ceacSChris Mason #include "disk-io.h" 30e089f05cSChris Mason #include "transaction.h" 310f7d52f4SChris Mason #include "btrfs_inode.h" 320b86a832SChris Mason #include "volumes.h" 33db94535dSChris Mason #include "print-tree.h" 34eb60ceacSChris Mason 355f39d397SChris Mason #if 0 365f39d397SChris Mason static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) 377eccb903SChris Mason { 385f39d397SChris Mason if (extent_buffer_blocknr(buf) != btrfs_header_blocknr(buf)) { 395f39d397SChris Mason printk(KERN_CRIT "buf blocknr(buf) is %llu, header is %llu\n", 405f39d397SChris Mason (unsigned long long)extent_buffer_blocknr(buf), 415f39d397SChris Mason (unsigned long long)btrfs_header_blocknr(buf)); 4239279cc3SChris Mason return 1; 43d98237b3SChris Mason } 449a8dd150SChris Mason return 0; 45eb60ceacSChris Mason } 465f39d397SChris Mason #endif 47eb60ceacSChris Mason 48d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops; 49ce9adaa5SChris Mason static struct workqueue_struct *end_io_workqueue; 50ce9adaa5SChris Mason 51ce9adaa5SChris Mason struct end_io_wq { 52ce9adaa5SChris Mason struct bio *bio; 53ce9adaa5SChris Mason bio_end_io_t *end_io; 54ce9adaa5SChris Mason void *private; 55ce9adaa5SChris Mason struct btrfs_fs_info *info; 56ce9adaa5SChris Mason int error; 57ce9adaa5SChris Mason struct list_head list; 58ce9adaa5SChris Mason }; 590da5468fSChris Mason 605f39d397SChris Mason struct extent_map *btree_get_extent(struct inode *inode, struct page *page, 61d1310b2eSChris Mason size_t page_offset, u64 start, u64 len, 625f39d397SChris Mason int create) 635f39d397SChris Mason { 645f39d397SChris Mason struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 655f39d397SChris Mason struct extent_map *em; 665f39d397SChris Mason int ret; 675f39d397SChris Mason 685f39d397SChris Mason again: 69d1310b2eSChris Mason spin_lock(&em_tree->lock); 70d1310b2eSChris Mason em = lookup_extent_mapping(em_tree, start, len); 71d1310b2eSChris Mason spin_unlock(&em_tree->lock); 725f39d397SChris Mason if (em) { 735f39d397SChris Mason goto out; 745f39d397SChris Mason } 755f39d397SChris Mason em = alloc_extent_map(GFP_NOFS); 765f39d397SChris Mason if (!em) { 775f39d397SChris Mason em = ERR_PTR(-ENOMEM); 785f39d397SChris Mason goto out; 795f39d397SChris Mason } 805f39d397SChris Mason em->start = 0; 81d1310b2eSChris Mason em->len = i_size_read(inode); 825f39d397SChris Mason em->block_start = 0; 835f39d397SChris Mason em->bdev = inode->i_sb->s_bdev; 84d1310b2eSChris Mason 85d1310b2eSChris Mason spin_lock(&em_tree->lock); 865f39d397SChris Mason ret = add_extent_mapping(em_tree, em); 87d1310b2eSChris Mason spin_unlock(&em_tree->lock); 88d1310b2eSChris Mason 895f39d397SChris Mason if (ret == -EEXIST) { 905f39d397SChris Mason free_extent_map(em); 915f39d397SChris Mason em = NULL; 925f39d397SChris Mason goto again; 935f39d397SChris Mason } else if (ret) { 945f39d397SChris Mason em = ERR_PTR(ret); 955f39d397SChris Mason } 965f39d397SChris Mason out: 975f39d397SChris Mason return em; 985f39d397SChris Mason } 995f39d397SChris Mason 10019c00ddcSChris Mason u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 10119c00ddcSChris Mason { 10219c00ddcSChris Mason return crc32c(seed, data, len); 10319c00ddcSChris Mason } 10419c00ddcSChris Mason 10519c00ddcSChris Mason void btrfs_csum_final(u32 crc, char *result) 10619c00ddcSChris Mason { 10719c00ddcSChris Mason *(__le32 *)result = ~cpu_to_le32(crc); 10819c00ddcSChris Mason } 10919c00ddcSChris Mason 11019c00ddcSChris Mason static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 11119c00ddcSChris Mason int verify) 11219c00ddcSChris Mason { 11319c00ddcSChris Mason char result[BTRFS_CRC32_SIZE]; 11419c00ddcSChris Mason unsigned long len; 11519c00ddcSChris Mason unsigned long cur_len; 11619c00ddcSChris Mason unsigned long offset = BTRFS_CSUM_SIZE; 11719c00ddcSChris Mason char *map_token = NULL; 11819c00ddcSChris Mason char *kaddr; 11919c00ddcSChris Mason unsigned long map_start; 12019c00ddcSChris Mason unsigned long map_len; 12119c00ddcSChris Mason int err; 12219c00ddcSChris Mason u32 crc = ~(u32)0; 12319c00ddcSChris Mason 12419c00ddcSChris Mason len = buf->len - offset; 12519c00ddcSChris Mason while(len > 0) { 12619c00ddcSChris Mason err = map_private_extent_buffer(buf, offset, 32, 12719c00ddcSChris Mason &map_token, &kaddr, 12819c00ddcSChris Mason &map_start, &map_len, KM_USER0); 12919c00ddcSChris Mason if (err) { 13019c00ddcSChris Mason printk("failed to map extent buffer! %lu\n", 13119c00ddcSChris Mason offset); 13219c00ddcSChris Mason return 1; 13319c00ddcSChris Mason } 13419c00ddcSChris Mason cur_len = min(len, map_len - (offset - map_start)); 13519c00ddcSChris Mason crc = btrfs_csum_data(root, kaddr + offset - map_start, 13619c00ddcSChris Mason crc, cur_len); 13719c00ddcSChris Mason len -= cur_len; 13819c00ddcSChris Mason offset += cur_len; 13919c00ddcSChris Mason unmap_extent_buffer(buf, map_token, KM_USER0); 14019c00ddcSChris Mason } 14119c00ddcSChris Mason btrfs_csum_final(crc, result); 14219c00ddcSChris Mason 14319c00ddcSChris Mason if (verify) { 144e4204dedSChris Mason int from_this_trans = 0; 145e4204dedSChris Mason 146e4204dedSChris Mason if (root->fs_info->running_transaction && 147e4204dedSChris Mason btrfs_header_generation(buf) == 148e4204dedSChris Mason root->fs_info->running_transaction->transid) 149e4204dedSChris Mason from_this_trans = 1; 150e4204dedSChris Mason 151e4204dedSChris Mason /* FIXME, this is not good */ 15263b10fc4SChris Mason if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 153e4204dedSChris Mason u32 val; 154e4204dedSChris Mason u32 found = 0; 155e4204dedSChris Mason memcpy(&found, result, BTRFS_CRC32_SIZE); 156e4204dedSChris Mason 157e4204dedSChris Mason read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE); 15863b10fc4SChris Mason WARN_ON(1); 159e4204dedSChris Mason printk("btrfs: %s checksum verify failed on %llu " 16063b10fc4SChris Mason "wanted %X found %X from_this_trans %d " 16163b10fc4SChris Mason "level %d\n", 16219c00ddcSChris Mason root->fs_info->sb->s_id, 16363b10fc4SChris Mason buf->start, val, found, from_this_trans, 16463b10fc4SChris Mason btrfs_header_level(buf)); 16519c00ddcSChris Mason return 1; 16619c00ddcSChris Mason } 16719c00ddcSChris Mason } else { 16819c00ddcSChris Mason write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 16919c00ddcSChris Mason } 17019c00ddcSChris Mason return 0; 17119c00ddcSChris Mason } 17219c00ddcSChris Mason 17319c00ddcSChris Mason 17419c00ddcSChris Mason int csum_dirty_buffer(struct btrfs_root *root, struct page *page) 17519c00ddcSChris Mason { 176d1310b2eSChris Mason struct extent_io_tree *tree; 17735ebb934SChris Mason u64 start = (u64)page->index << PAGE_CACHE_SHIFT; 17819c00ddcSChris Mason u64 found_start; 17919c00ddcSChris Mason int found_level; 18019c00ddcSChris Mason unsigned long len; 18119c00ddcSChris Mason struct extent_buffer *eb; 182d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 18319c00ddcSChris Mason 18419c00ddcSChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 18519c00ddcSChris Mason goto out; 18619c00ddcSChris Mason if (!page->private) 18719c00ddcSChris Mason goto out; 18819c00ddcSChris Mason len = page->private >> 2; 18919c00ddcSChris Mason if (len == 0) { 19019c00ddcSChris Mason WARN_ON(1); 19119c00ddcSChris Mason } 19219c00ddcSChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 193a86c12c7SChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1, 194a86c12c7SChris Mason btree_get_extent); 195e18e4809SChris Mason btrfs_clear_buffer_defrag(eb); 19619c00ddcSChris Mason found_start = btrfs_header_bytenr(eb); 19719c00ddcSChris Mason if (found_start != start) { 19819c00ddcSChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 19919c00ddcSChris Mason start, found_start, len); 20055c69072SChris Mason WARN_ON(1); 20155c69072SChris Mason goto err; 20255c69072SChris Mason } 20355c69072SChris Mason if (eb->first_page != page) { 20455c69072SChris Mason printk("bad first page %lu %lu\n", eb->first_page->index, 20555c69072SChris Mason page->index); 20655c69072SChris Mason WARN_ON(1); 20755c69072SChris Mason goto err; 20855c69072SChris Mason } 20955c69072SChris Mason if (!PageUptodate(page)) { 21055c69072SChris Mason printk("csum not up to date page %lu\n", page->index); 21155c69072SChris Mason WARN_ON(1); 21255c69072SChris Mason goto err; 21319c00ddcSChris Mason } 21419c00ddcSChris Mason found_level = btrfs_header_level(eb); 21563b10fc4SChris Mason spin_lock(&root->fs_info->hash_lock); 21663b10fc4SChris Mason btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); 21763b10fc4SChris Mason spin_unlock(&root->fs_info->hash_lock); 21819c00ddcSChris Mason csum_tree_block(root, eb, 0); 21955c69072SChris Mason err: 22019c00ddcSChris Mason free_extent_buffer(eb); 22119c00ddcSChris Mason out: 22219c00ddcSChris Mason return 0; 22319c00ddcSChris Mason } 22419c00ddcSChris Mason 2250da5468fSChris Mason static int btree_writepage_io_hook(struct page *page, u64 start, u64 end) 2260da5468fSChris Mason { 2270da5468fSChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 2280da5468fSChris Mason 2290da5468fSChris Mason csum_dirty_buffer(root, page); 2300da5468fSChris Mason return 0; 2310da5468fSChris Mason } 2320da5468fSChris Mason 233ce9adaa5SChris Mason int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, 234ce9adaa5SChris Mason struct extent_state *state) 235ce9adaa5SChris Mason { 236ce9adaa5SChris Mason struct extent_io_tree *tree; 237ce9adaa5SChris Mason u64 found_start; 238ce9adaa5SChris Mason int found_level; 239ce9adaa5SChris Mason unsigned long len; 240ce9adaa5SChris Mason struct extent_buffer *eb; 241ce9adaa5SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 242ce9adaa5SChris Mason int ret; 243ce9adaa5SChris Mason 244ce9adaa5SChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 245ce9adaa5SChris Mason if (page->private == EXTENT_PAGE_PRIVATE) 246ce9adaa5SChris Mason goto out; 247ce9adaa5SChris Mason if (!page->private) 248ce9adaa5SChris Mason goto out; 249ce9adaa5SChris Mason len = page->private >> 2; 250ce9adaa5SChris Mason if (len == 0) { 251ce9adaa5SChris Mason WARN_ON(1); 252ce9adaa5SChris Mason } 253ce9adaa5SChris Mason eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); 254ce9adaa5SChris Mason read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1, 255ce9adaa5SChris Mason btree_get_extent); 256ce9adaa5SChris Mason btrfs_clear_buffer_defrag(eb); 257ce9adaa5SChris Mason found_start = btrfs_header_bytenr(eb); 258ce9adaa5SChris Mason if (found_start != start) { 259ce9adaa5SChris Mason printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", 260ce9adaa5SChris Mason start, found_start, len); 261ce9adaa5SChris Mason WARN_ON(1); 262ce9adaa5SChris Mason goto err; 263ce9adaa5SChris Mason } 264ce9adaa5SChris Mason if (eb->first_page != page) { 265ce9adaa5SChris Mason printk("bad first page %lu %lu\n", eb->first_page->index, 266ce9adaa5SChris Mason page->index); 267ce9adaa5SChris Mason WARN_ON(1); 268ce9adaa5SChris Mason goto err; 269ce9adaa5SChris Mason } 270ce9adaa5SChris Mason found_level = btrfs_header_level(eb); 271ce9adaa5SChris Mason 272ce9adaa5SChris Mason ret = csum_tree_block(root, eb, 1); 273ce9adaa5SChris Mason 274ce9adaa5SChris Mason end = min_t(u64, eb->len, PAGE_CACHE_SIZE); 275ce9adaa5SChris Mason end = eb->start + end - 1; 276ce9adaa5SChris Mason release_extent_buffer_tail_pages(eb); 277ce9adaa5SChris Mason err: 278ce9adaa5SChris Mason free_extent_buffer(eb); 279ce9adaa5SChris Mason out: 280ce9adaa5SChris Mason return 0; 281ce9adaa5SChris Mason } 282ce9adaa5SChris Mason 283ce9adaa5SChris Mason #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) 284ce9adaa5SChris Mason static void end_workqueue_bio(struct bio *bio, int err) 285ce9adaa5SChris Mason #else 286ce9adaa5SChris Mason static int end_workqueue_bio(struct bio *bio, 287ce9adaa5SChris Mason unsigned int bytes_done, int err) 288ce9adaa5SChris Mason #endif 289ce9adaa5SChris Mason { 290ce9adaa5SChris Mason struct end_io_wq *end_io_wq = bio->bi_private; 291ce9adaa5SChris Mason struct btrfs_fs_info *fs_info; 292ce9adaa5SChris Mason unsigned long flags; 293ce9adaa5SChris Mason 294ce9adaa5SChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) 295ce9adaa5SChris Mason if (bio->bi_size) 296ce9adaa5SChris Mason return 1; 297ce9adaa5SChris Mason #endif 298ce9adaa5SChris Mason 299ce9adaa5SChris Mason fs_info = end_io_wq->info; 300ce9adaa5SChris Mason spin_lock_irqsave(&fs_info->end_io_work_lock, flags); 301ce9adaa5SChris Mason end_io_wq->error = err; 302ce9adaa5SChris Mason list_add_tail(&end_io_wq->list, &fs_info->end_io_work_list); 303ce9adaa5SChris Mason spin_unlock_irqrestore(&fs_info->end_io_work_lock, flags); 304ce9adaa5SChris Mason queue_work(end_io_workqueue, &fs_info->end_io_work); 305ce9adaa5SChris Mason 306ce9adaa5SChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) 307ce9adaa5SChris Mason return 0; 308ce9adaa5SChris Mason #endif 309ce9adaa5SChris Mason } 310ce9adaa5SChris Mason 3110b86a832SChris Mason static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) 3120b86a832SChris Mason { 3130b86a832SChris Mason struct btrfs_root *root = BTRFS_I(inode)->root; 314ce9adaa5SChris Mason struct end_io_wq *end_io_wq; 3150b86a832SChris Mason u64 offset; 3160b86a832SChris Mason offset = bio->bi_sector << 9; 317ce9adaa5SChris Mason 318ce9adaa5SChris Mason if (rw & (1 << BIO_RW)) { 319ce9adaa5SChris Mason return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio); 320ce9adaa5SChris Mason } 321ce9adaa5SChris Mason 322ce9adaa5SChris Mason end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS); 323ce9adaa5SChris Mason if (!end_io_wq) 324ce9adaa5SChris Mason return -ENOMEM; 325ce9adaa5SChris Mason 326ce9adaa5SChris Mason end_io_wq->private = bio->bi_private; 327ce9adaa5SChris Mason end_io_wq->end_io = bio->bi_end_io; 328ce9adaa5SChris Mason end_io_wq->info = root->fs_info; 329ce9adaa5SChris Mason end_io_wq->error = 0; 330ce9adaa5SChris Mason end_io_wq->bio = bio; 331ce9adaa5SChris Mason 332ce9adaa5SChris Mason bio->bi_private = end_io_wq; 333ce9adaa5SChris Mason bio->bi_end_io = end_workqueue_bio; 334ce9adaa5SChris Mason 3350b86a832SChris Mason if (offset == BTRFS_SUPER_INFO_OFFSET) { 3360b86a832SChris Mason bio->bi_bdev = root->fs_info->sb->s_bdev; 3370b86a832SChris Mason submit_bio(rw, bio); 3380b86a832SChris Mason return 0; 3390b86a832SChris Mason } 3400b86a832SChris Mason return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio); 3410b86a832SChris Mason } 3420b86a832SChris Mason 3435f39d397SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 3445f39d397SChris Mason { 345d1310b2eSChris Mason struct extent_io_tree *tree; 346d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 3475f39d397SChris Mason return extent_write_full_page(tree, page, btree_get_extent, wbc); 3485f39d397SChris Mason } 3490da5468fSChris Mason 3500da5468fSChris Mason static int btree_writepages(struct address_space *mapping, 3510da5468fSChris Mason struct writeback_control *wbc) 3520da5468fSChris Mason { 353d1310b2eSChris Mason struct extent_io_tree *tree; 354d1310b2eSChris Mason tree = &BTRFS_I(mapping->host)->io_tree; 355d8d5f3e1SChris Mason if (wbc->sync_mode == WB_SYNC_NONE) { 356793955bcSChris Mason u64 num_dirty; 357793955bcSChris Mason u64 start = 0; 358793955bcSChris Mason unsigned long thresh = 96 * 1024 * 1024; 359448d640bSChris Mason 360448d640bSChris Mason if (wbc->for_kupdate) 361448d640bSChris Mason return 0; 362448d640bSChris Mason 363ca664626SChris Mason if (current_is_pdflush()) { 364ca664626SChris Mason thresh = 96 * 1024 * 1024; 365ca664626SChris Mason } else { 366ca664626SChris Mason thresh = 8 * 1024 * 1024; 367ca664626SChris Mason } 3681832a6d5SChris Mason num_dirty = count_range_bits(tree, &start, (u64)-1, 3691832a6d5SChris Mason thresh, EXTENT_DIRTY); 370793955bcSChris Mason if (num_dirty < thresh) { 371793955bcSChris Mason return 0; 372793955bcSChris Mason } 373793955bcSChris Mason } 3740da5468fSChris Mason return extent_writepages(tree, mapping, btree_get_extent, wbc); 3750da5468fSChris Mason } 3760da5468fSChris Mason 3775f39d397SChris Mason int btree_readpage(struct file *file, struct page *page) 3785f39d397SChris Mason { 379d1310b2eSChris Mason struct extent_io_tree *tree; 380d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 3815f39d397SChris Mason return extent_read_full_page(tree, page, btree_get_extent); 3825f39d397SChris Mason } 3835f39d397SChris Mason 38470dec807SChris Mason static int btree_releasepage(struct page *page, gfp_t gfp_flags) 3855f39d397SChris Mason { 386d1310b2eSChris Mason struct extent_io_tree *tree; 387d1310b2eSChris Mason struct extent_map_tree *map; 3885f39d397SChris Mason int ret; 3895f39d397SChris Mason 390d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 391d1310b2eSChris Mason map = &BTRFS_I(page->mapping->host)->extent_tree; 39270dec807SChris Mason ret = try_release_extent_mapping(map, tree, page, gfp_flags); 3935f39d397SChris Mason if (ret == 1) { 394728131d8SChris Mason invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE); 3955f39d397SChris Mason ClearPagePrivate(page); 3965f39d397SChris Mason set_page_private(page, 0); 397d98237b3SChris Mason page_cache_release(page); 3985f39d397SChris Mason } 399d98237b3SChris Mason return ret; 400d98237b3SChris Mason } 401d98237b3SChris Mason 4025f39d397SChris Mason static void btree_invalidatepage(struct page *page, unsigned long offset) 403d98237b3SChris Mason { 404d1310b2eSChris Mason struct extent_io_tree *tree; 405d1310b2eSChris Mason tree = &BTRFS_I(page->mapping->host)->io_tree; 4065f39d397SChris Mason extent_invalidatepage(tree, page, offset); 4075f39d397SChris Mason btree_releasepage(page, GFP_NOFS); 408d98237b3SChris Mason } 409d98237b3SChris Mason 4105f39d397SChris Mason #if 0 411d98237b3SChris Mason static int btree_writepage(struct page *page, struct writeback_control *wbc) 412d98237b3SChris Mason { 41387cbda5cSChris Mason struct buffer_head *bh; 4140f7d52f4SChris Mason struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 41587cbda5cSChris Mason struct buffer_head *head; 41687cbda5cSChris Mason if (!page_has_buffers(page)) { 41787cbda5cSChris Mason create_empty_buffers(page, root->fs_info->sb->s_blocksize, 41887cbda5cSChris Mason (1 << BH_Dirty)|(1 << BH_Uptodate)); 41987cbda5cSChris Mason } 42087cbda5cSChris Mason head = page_buffers(page); 42187cbda5cSChris Mason bh = head; 42287cbda5cSChris Mason do { 42387cbda5cSChris Mason if (buffer_dirty(bh)) 42487cbda5cSChris Mason csum_tree_block(root, bh, 0); 42587cbda5cSChris Mason bh = bh->b_this_page; 42687cbda5cSChris Mason } while (bh != head); 427d98237b3SChris Mason return block_write_full_page(page, btree_get_block, wbc); 428d98237b3SChris Mason } 4295f39d397SChris Mason #endif 430d98237b3SChris Mason 431d98237b3SChris Mason static struct address_space_operations btree_aops = { 432d98237b3SChris Mason .readpage = btree_readpage, 433d98237b3SChris Mason .writepage = btree_writepage, 4340da5468fSChris Mason .writepages = btree_writepages, 4355f39d397SChris Mason .releasepage = btree_releasepage, 4365f39d397SChris Mason .invalidatepage = btree_invalidatepage, 437d98237b3SChris Mason .sync_page = block_sync_page, 438d98237b3SChris Mason }; 439123abc88SChris Mason 440db94535dSChris Mason int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) 441090d1875SChris Mason { 4425f39d397SChris Mason struct extent_buffer *buf = NULL; 4435f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 444de428b63SChris Mason int ret = 0; 445090d1875SChris Mason 446db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 4475f39d397SChris Mason if (!buf) 448090d1875SChris Mason return 0; 449d1310b2eSChris Mason read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 450a86c12c7SChris Mason buf, 0, 0, btree_get_extent); 4515f39d397SChris Mason free_extent_buffer(buf); 452de428b63SChris Mason return ret; 453090d1875SChris Mason } 454090d1875SChris Mason 4550b86a832SChris Mason static int close_all_devices(struct btrfs_fs_info *fs_info) 4560b86a832SChris Mason { 4570b86a832SChris Mason struct list_head *list; 4580b86a832SChris Mason struct list_head *next; 4590b86a832SChris Mason struct btrfs_device *device; 4600b86a832SChris Mason 4618a4b83ccSChris Mason list = &fs_info->fs_devices->devices; 4628a4b83ccSChris Mason list_for_each(next, list) { 4630b86a832SChris Mason device = list_entry(next, struct btrfs_device, dev_list); 4648a4b83ccSChris Mason if (device->bdev && device->bdev != fs_info->sb->s_bdev) 4658a4b83ccSChris Mason close_bdev_excl(device->bdev); 4668a4b83ccSChris Mason device->bdev = NULL; 4670b86a832SChris Mason } 4680b86a832SChris Mason return 0; 4690b86a832SChris Mason } 4700b86a832SChris Mason 4710999df54SChris Mason int btrfs_verify_block_csum(struct btrfs_root *root, 4720999df54SChris Mason struct extent_buffer *buf) 4730999df54SChris Mason { 474ce9adaa5SChris Mason return btrfs_buffer_uptodate(buf); 4750999df54SChris Mason } 4760999df54SChris Mason 4770999df54SChris Mason struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, 4780999df54SChris Mason u64 bytenr, u32 blocksize) 4790999df54SChris Mason { 4800999df54SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 4810999df54SChris Mason struct extent_buffer *eb; 4820999df54SChris Mason eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 4830999df54SChris Mason bytenr, blocksize, GFP_NOFS); 4840999df54SChris Mason return eb; 4850999df54SChris Mason } 4860999df54SChris Mason 4870999df54SChris Mason struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, 4880999df54SChris Mason u64 bytenr, u32 blocksize) 4890999df54SChris Mason { 4900999df54SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 4910999df54SChris Mason struct extent_buffer *eb; 4920999df54SChris Mason 4930999df54SChris Mason eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree, 4940999df54SChris Mason bytenr, blocksize, NULL, GFP_NOFS); 4950999df54SChris Mason return eb; 4960999df54SChris Mason } 4970999df54SChris Mason 4980999df54SChris Mason 499db94535dSChris Mason struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 500db94535dSChris Mason u32 blocksize) 501e20d96d6SChris Mason { 5025f39d397SChris Mason struct extent_buffer *buf = NULL; 5035f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 504d1310b2eSChris Mason struct extent_io_tree *io_tree; 50519c00ddcSChris Mason int ret; 50619c00ddcSChris Mason 507d1310b2eSChris Mason io_tree = &BTRFS_I(btree_inode)->io_tree; 508e20d96d6SChris Mason 509db94535dSChris Mason buf = btrfs_find_create_tree_block(root, bytenr, blocksize); 5105f39d397SChris Mason if (!buf) 511d98237b3SChris Mason return NULL; 512e4204dedSChris Mason 513ce9adaa5SChris Mason ret = read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 514ce9adaa5SChris Mason 1, btree_get_extent); 515ce9adaa5SChris Mason 516ce9adaa5SChris Mason if (ret == 0) { 517ce9adaa5SChris Mason buf->flags |= EXTENT_UPTODATE; 518ce9adaa5SChris Mason } 5195f39d397SChris Mason return buf; 520ce9adaa5SChris Mason 521eb60ceacSChris Mason } 522eb60ceacSChris Mason 523e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 5245f39d397SChris Mason struct extent_buffer *buf) 525ed2ff2cbSChris Mason { 5265f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 52755c69072SChris Mason if (btrfs_header_generation(buf) == 52855c69072SChris Mason root->fs_info->running_transaction->transid) 529d1310b2eSChris Mason clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, 53055c69072SChris Mason buf); 5315f39d397SChris Mason return 0; 5325f39d397SChris Mason } 5335f39d397SChris Mason 5345f39d397SChris Mason int wait_on_tree_block_writeback(struct btrfs_root *root, 5355f39d397SChris Mason struct extent_buffer *buf) 5365f39d397SChris Mason { 5375f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 538d1310b2eSChris Mason wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->io_tree, 5395f39d397SChris Mason buf); 5405f39d397SChris Mason return 0; 5415f39d397SChris Mason } 5425f39d397SChris Mason 543db94535dSChris Mason static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, 54487ee04ebSChris Mason u32 stripesize, struct btrfs_root *root, 5459f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 546e20d96d6SChris Mason u64 objectid) 547d97e63b6SChris Mason { 548cfaa7295SChris Mason root->node = NULL; 5490f7d52f4SChris Mason root->inode = NULL; 550a28ec197SChris Mason root->commit_root = NULL; 551db94535dSChris Mason root->sectorsize = sectorsize; 552db94535dSChris Mason root->nodesize = nodesize; 553db94535dSChris Mason root->leafsize = leafsize; 55487ee04ebSChris Mason root->stripesize = stripesize; 555123abc88SChris Mason root->ref_cows = 0; 5560b86a832SChris Mason root->track_dirty = 0; 5570b86a832SChris Mason 5589f5fae2fSChris Mason root->fs_info = fs_info; 5590f7d52f4SChris Mason root->objectid = objectid; 5600f7d52f4SChris Mason root->last_trans = 0; 5611b05da2eSChris Mason root->highest_inode = 0; 5621b05da2eSChris Mason root->last_inode_alloc = 0; 56358176a96SJosef Bacik root->name = NULL; 5644313b399SChris Mason root->in_sysfs = 0; 5650b86a832SChris Mason 5660b86a832SChris Mason INIT_LIST_HEAD(&root->dirty_list); 5673768f368SChris Mason memset(&root->root_key, 0, sizeof(root->root_key)); 5683768f368SChris Mason memset(&root->root_item, 0, sizeof(root->root_item)); 5696702ed49SChris Mason memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 57058176a96SJosef Bacik memset(&root->root_kobj, 0, sizeof(root->root_kobj)); 57158176a96SJosef Bacik init_completion(&root->kobj_unregister); 5726702ed49SChris Mason root->defrag_running = 0; 5736702ed49SChris Mason root->defrag_level = 0; 5744d775673SChris Mason root->root_key.objectid = objectid; 5753768f368SChris Mason return 0; 5763768f368SChris Mason } 5773768f368SChris Mason 578db94535dSChris Mason static int find_and_setup_root(struct btrfs_root *tree_root, 5799f5fae2fSChris Mason struct btrfs_fs_info *fs_info, 5809f5fae2fSChris Mason u64 objectid, 581e20d96d6SChris Mason struct btrfs_root *root) 5823768f368SChris Mason { 5833768f368SChris Mason int ret; 584db94535dSChris Mason u32 blocksize; 5853768f368SChris Mason 586db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 58787ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 58887ee04ebSChris Mason root, fs_info, objectid); 5893768f368SChris Mason ret = btrfs_find_last_root(tree_root, objectid, 5903768f368SChris Mason &root->root_item, &root->root_key); 5913768f368SChris Mason BUG_ON(ret); 5923768f368SChris Mason 593db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 594db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 595db94535dSChris Mason blocksize); 5963768f368SChris Mason BUG_ON(!root->node); 597d97e63b6SChris Mason return 0; 598d97e63b6SChris Mason } 599d97e63b6SChris Mason 6005eda7b5eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 6010f7d52f4SChris Mason struct btrfs_key *location) 6020f7d52f4SChris Mason { 6030f7d52f4SChris Mason struct btrfs_root *root; 6040f7d52f4SChris Mason struct btrfs_root *tree_root = fs_info->tree_root; 6050f7d52f4SChris Mason struct btrfs_path *path; 6065f39d397SChris Mason struct extent_buffer *l; 6071b05da2eSChris Mason u64 highest_inode; 608db94535dSChris Mason u32 blocksize; 6090f7d52f4SChris Mason int ret = 0; 6100f7d52f4SChris Mason 6115eda7b5eSChris Mason root = kzalloc(sizeof(*root), GFP_NOFS); 6120cf6c620SChris Mason if (!root) 6130f7d52f4SChris Mason return ERR_PTR(-ENOMEM); 6140f7d52f4SChris Mason if (location->offset == (u64)-1) { 615db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 6160f7d52f4SChris Mason location->objectid, root); 6170f7d52f4SChris Mason if (ret) { 6180f7d52f4SChris Mason kfree(root); 6190f7d52f4SChris Mason return ERR_PTR(ret); 6200f7d52f4SChris Mason } 6210f7d52f4SChris Mason goto insert; 6220f7d52f4SChris Mason } 6230f7d52f4SChris Mason 624db94535dSChris Mason __setup_root(tree_root->nodesize, tree_root->leafsize, 62587ee04ebSChris Mason tree_root->sectorsize, tree_root->stripesize, 62687ee04ebSChris Mason root, fs_info, location->objectid); 6270f7d52f4SChris Mason 6280f7d52f4SChris Mason path = btrfs_alloc_path(); 6290f7d52f4SChris Mason BUG_ON(!path); 6300f7d52f4SChris Mason ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 6310f7d52f4SChris Mason if (ret != 0) { 6320f7d52f4SChris Mason if (ret > 0) 6330f7d52f4SChris Mason ret = -ENOENT; 6340f7d52f4SChris Mason goto out; 6350f7d52f4SChris Mason } 6365f39d397SChris Mason l = path->nodes[0]; 6375f39d397SChris Mason read_extent_buffer(l, &root->root_item, 6385f39d397SChris Mason btrfs_item_ptr_offset(l, path->slots[0]), 6390f7d52f4SChris Mason sizeof(root->root_item)); 64044b36eb2SYan Zheng memcpy(&root->root_key, location, sizeof(*location)); 6410f7d52f4SChris Mason ret = 0; 6420f7d52f4SChris Mason out: 6430f7d52f4SChris Mason btrfs_release_path(root, path); 6440f7d52f4SChris Mason btrfs_free_path(path); 6450f7d52f4SChris Mason if (ret) { 6460f7d52f4SChris Mason kfree(root); 6470f7d52f4SChris Mason return ERR_PTR(ret); 6480f7d52f4SChris Mason } 649db94535dSChris Mason blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 650db94535dSChris Mason root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 651db94535dSChris Mason blocksize); 6520f7d52f4SChris Mason BUG_ON(!root->node); 6530f7d52f4SChris Mason insert: 6540f7d52f4SChris Mason root->ref_cows = 1; 6555eda7b5eSChris Mason ret = btrfs_find_highest_inode(root, &highest_inode); 6565eda7b5eSChris Mason if (ret == 0) { 6575eda7b5eSChris Mason root->highest_inode = highest_inode; 6585eda7b5eSChris Mason root->last_inode_alloc = highest_inode; 6595eda7b5eSChris Mason } 6605eda7b5eSChris Mason return root; 6615eda7b5eSChris Mason } 6625eda7b5eSChris Mason 663dc17ff8fSChris Mason struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, 664dc17ff8fSChris Mason u64 root_objectid) 665dc17ff8fSChris Mason { 666dc17ff8fSChris Mason struct btrfs_root *root; 667dc17ff8fSChris Mason 668dc17ff8fSChris Mason if (root_objectid == BTRFS_ROOT_TREE_OBJECTID) 669dc17ff8fSChris Mason return fs_info->tree_root; 670dc17ff8fSChris Mason if (root_objectid == BTRFS_EXTENT_TREE_OBJECTID) 671dc17ff8fSChris Mason return fs_info->extent_root; 672dc17ff8fSChris Mason 673dc17ff8fSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 674dc17ff8fSChris Mason (unsigned long)root_objectid); 675dc17ff8fSChris Mason return root; 676dc17ff8fSChris Mason } 677dc17ff8fSChris Mason 678edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, 679edbd8d4eSChris Mason struct btrfs_key *location) 6805eda7b5eSChris Mason { 6815eda7b5eSChris Mason struct btrfs_root *root; 6825eda7b5eSChris Mason int ret; 6835eda7b5eSChris Mason 684edbd8d4eSChris Mason if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) 685edbd8d4eSChris Mason return fs_info->tree_root; 686edbd8d4eSChris Mason if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID) 687edbd8d4eSChris Mason return fs_info->extent_root; 688edbd8d4eSChris Mason 6895eda7b5eSChris Mason root = radix_tree_lookup(&fs_info->fs_roots_radix, 6905eda7b5eSChris Mason (unsigned long)location->objectid); 6915eda7b5eSChris Mason if (root) 6925eda7b5eSChris Mason return root; 6935eda7b5eSChris Mason 6945eda7b5eSChris Mason root = btrfs_read_fs_root_no_radix(fs_info, location); 6955eda7b5eSChris Mason if (IS_ERR(root)) 6965eda7b5eSChris Mason return root; 6972619ba1fSChris Mason ret = radix_tree_insert(&fs_info->fs_roots_radix, 6982619ba1fSChris Mason (unsigned long)root->root_key.objectid, 6990f7d52f4SChris Mason root); 7000f7d52f4SChris Mason if (ret) { 7015f39d397SChris Mason free_extent_buffer(root->node); 7020f7d52f4SChris Mason kfree(root); 7030f7d52f4SChris Mason return ERR_PTR(ret); 7040f7d52f4SChris Mason } 705edbd8d4eSChris Mason ret = btrfs_find_dead_roots(fs_info->tree_root, 706edbd8d4eSChris Mason root->root_key.objectid, root); 707edbd8d4eSChris Mason BUG_ON(ret); 708edbd8d4eSChris Mason 709edbd8d4eSChris Mason return root; 710edbd8d4eSChris Mason } 711edbd8d4eSChris Mason 712edbd8d4eSChris Mason struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 713edbd8d4eSChris Mason struct btrfs_key *location, 714edbd8d4eSChris Mason const char *name, int namelen) 715edbd8d4eSChris Mason { 716edbd8d4eSChris Mason struct btrfs_root *root; 717edbd8d4eSChris Mason int ret; 718edbd8d4eSChris Mason 719edbd8d4eSChris Mason root = btrfs_read_fs_root_no_name(fs_info, location); 720edbd8d4eSChris Mason if (!root) 721edbd8d4eSChris Mason return NULL; 72258176a96SJosef Bacik 7234313b399SChris Mason if (root->in_sysfs) 7244313b399SChris Mason return root; 7254313b399SChris Mason 72658176a96SJosef Bacik ret = btrfs_set_root_name(root, name, namelen); 72758176a96SJosef Bacik if (ret) { 7285f39d397SChris Mason free_extent_buffer(root->node); 72958176a96SJosef Bacik kfree(root); 73058176a96SJosef Bacik return ERR_PTR(ret); 73158176a96SJosef Bacik } 73258176a96SJosef Bacik 73358176a96SJosef Bacik ret = btrfs_sysfs_add_root(root); 73458176a96SJosef Bacik if (ret) { 7355f39d397SChris Mason free_extent_buffer(root->node); 73658176a96SJosef Bacik kfree(root->name); 73758176a96SJosef Bacik kfree(root); 73858176a96SJosef Bacik return ERR_PTR(ret); 73958176a96SJosef Bacik } 7404313b399SChris Mason root->in_sysfs = 1; 7410f7d52f4SChris Mason return root; 7420f7d52f4SChris Mason } 74319c00ddcSChris Mason #if 0 74419c00ddcSChris Mason static int add_hasher(struct btrfs_fs_info *info, char *type) { 74519c00ddcSChris Mason struct btrfs_hasher *hasher; 7460f7d52f4SChris Mason 74719c00ddcSChris Mason hasher = kmalloc(sizeof(*hasher), GFP_NOFS); 74819c00ddcSChris Mason if (!hasher) 74919c00ddcSChris Mason return -ENOMEM; 75019c00ddcSChris Mason hasher->hash_tfm = crypto_alloc_hash(type, 0, CRYPTO_ALG_ASYNC); 75119c00ddcSChris Mason if (!hasher->hash_tfm) { 75219c00ddcSChris Mason kfree(hasher); 75319c00ddcSChris Mason return -EINVAL; 75419c00ddcSChris Mason } 75519c00ddcSChris Mason spin_lock(&info->hash_lock); 75619c00ddcSChris Mason list_add(&hasher->list, &info->hashers); 75719c00ddcSChris Mason spin_unlock(&info->hash_lock); 75819c00ddcSChris Mason return 0; 75919c00ddcSChris Mason } 76019c00ddcSChris Mason #endif 76104160088SChris Mason 76204160088SChris Mason static int btrfs_congested_fn(void *congested_data, int bdi_bits) 76304160088SChris Mason { 76404160088SChris Mason struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data; 76504160088SChris Mason int ret = 0; 76604160088SChris Mason struct list_head *cur; 76704160088SChris Mason struct btrfs_device *device; 76804160088SChris Mason struct backing_dev_info *bdi; 76904160088SChris Mason 77004160088SChris Mason list_for_each(cur, &info->fs_devices->devices) { 77104160088SChris Mason device = list_entry(cur, struct btrfs_device, dev_list); 77204160088SChris Mason bdi = blk_get_backing_dev_info(device->bdev); 77304160088SChris Mason if (bdi && bdi_congested(bdi, bdi_bits)) { 77404160088SChris Mason ret = 1; 77504160088SChris Mason break; 77604160088SChris Mason } 77704160088SChris Mason } 77804160088SChris Mason return ret; 77904160088SChris Mason } 78004160088SChris Mason 78104160088SChris Mason void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) 78204160088SChris Mason { 78304160088SChris Mason struct list_head *cur; 78404160088SChris Mason struct btrfs_device *device; 78504160088SChris Mason struct btrfs_fs_info *info; 78604160088SChris Mason 78704160088SChris Mason info = (struct btrfs_fs_info *)bdi->unplug_io_data; 78804160088SChris Mason list_for_each(cur, &info->fs_devices->devices) { 78904160088SChris Mason device = list_entry(cur, struct btrfs_device, dev_list); 79004160088SChris Mason bdi = blk_get_backing_dev_info(device->bdev); 79104160088SChris Mason if (bdi->unplug_io_fn) { 79204160088SChris Mason bdi->unplug_io_fn(bdi, page); 79304160088SChris Mason } 79404160088SChris Mason } 79504160088SChris Mason } 79604160088SChris Mason 79704160088SChris Mason static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) 79804160088SChris Mason { 79904160088SChris Mason bdi_init(bdi); 80083041addSChris Mason bdi->ra_pages = default_backing_dev_info.ra_pages * 4; 80104160088SChris Mason bdi->state = 0; 80204160088SChris Mason bdi->capabilities = default_backing_dev_info.capabilities; 80304160088SChris Mason bdi->unplug_io_fn = btrfs_unplug_io_fn; 80404160088SChris Mason bdi->unplug_io_data = info; 80504160088SChris Mason bdi->congested_fn = btrfs_congested_fn; 80604160088SChris Mason bdi->congested_data = info; 80704160088SChris Mason return 0; 80804160088SChris Mason } 80904160088SChris Mason 810ce9adaa5SChris Mason static int bio_ready_for_csum(struct bio *bio) 811ce9adaa5SChris Mason { 812ce9adaa5SChris Mason u64 length = 0; 813ce9adaa5SChris Mason u64 buf_len = 0; 814ce9adaa5SChris Mason u64 start = 0; 815ce9adaa5SChris Mason struct page *page; 816ce9adaa5SChris Mason struct extent_io_tree *io_tree = NULL; 817ce9adaa5SChris Mason struct btrfs_fs_info *info = NULL; 818ce9adaa5SChris Mason struct bio_vec *bvec; 819ce9adaa5SChris Mason int i; 820ce9adaa5SChris Mason int ret; 821ce9adaa5SChris Mason 822ce9adaa5SChris Mason bio_for_each_segment(bvec, bio, i) { 823ce9adaa5SChris Mason page = bvec->bv_page; 824ce9adaa5SChris Mason if (page->private == EXTENT_PAGE_PRIVATE) { 825ce9adaa5SChris Mason length += bvec->bv_len; 826ce9adaa5SChris Mason continue; 827ce9adaa5SChris Mason } 828ce9adaa5SChris Mason if (!page->private) { 829ce9adaa5SChris Mason length += bvec->bv_len; 830ce9adaa5SChris Mason continue; 831ce9adaa5SChris Mason } 832ce9adaa5SChris Mason length = bvec->bv_len; 833ce9adaa5SChris Mason buf_len = page->private >> 2; 834ce9adaa5SChris Mason start = page_offset(page) + bvec->bv_offset; 835ce9adaa5SChris Mason io_tree = &BTRFS_I(page->mapping->host)->io_tree; 836ce9adaa5SChris Mason info = BTRFS_I(page->mapping->host)->root->fs_info; 837ce9adaa5SChris Mason } 838ce9adaa5SChris Mason /* are we fully contained in this bio? */ 839ce9adaa5SChris Mason if (buf_len <= length) 840ce9adaa5SChris Mason return 1; 841ce9adaa5SChris Mason 842ce9adaa5SChris Mason ret = extent_range_uptodate(io_tree, start + length, 843ce9adaa5SChris Mason start + buf_len - 1); 844ce9adaa5SChris Mason if (ret == 1) 845ce9adaa5SChris Mason return ret; 846ce9adaa5SChris Mason return ret; 847ce9adaa5SChris Mason } 848ce9adaa5SChris Mason 849ce9adaa5SChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 850ce9adaa5SChris Mason void btrfs_end_io_csum(void *p) 851ce9adaa5SChris Mason #else 852ce9adaa5SChris Mason void btrfs_end_io_csum(struct work_struct *work) 853ce9adaa5SChris Mason #endif 854ce9adaa5SChris Mason { 855ce9adaa5SChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 856ce9adaa5SChris Mason struct btrfs_fs_info *fs_info = p; 857ce9adaa5SChris Mason #else 858ce9adaa5SChris Mason struct btrfs_fs_info *fs_info = container_of(work, 859ce9adaa5SChris Mason struct btrfs_fs_info, 860ce9adaa5SChris Mason end_io_work); 861ce9adaa5SChris Mason #endif 862ce9adaa5SChris Mason unsigned long flags; 863ce9adaa5SChris Mason struct end_io_wq *end_io_wq; 864ce9adaa5SChris Mason struct bio *bio; 865ce9adaa5SChris Mason struct list_head *next; 866ce9adaa5SChris Mason int error; 867ce9adaa5SChris Mason int was_empty; 868ce9adaa5SChris Mason 869ce9adaa5SChris Mason while(1) { 870ce9adaa5SChris Mason spin_lock_irqsave(&fs_info->end_io_work_lock, flags); 871ce9adaa5SChris Mason if (list_empty(&fs_info->end_io_work_list)) { 872ce9adaa5SChris Mason spin_unlock_irqrestore(&fs_info->end_io_work_lock, 873ce9adaa5SChris Mason flags); 874ce9adaa5SChris Mason return; 875ce9adaa5SChris Mason } 876ce9adaa5SChris Mason next = fs_info->end_io_work_list.next; 877ce9adaa5SChris Mason list_del(next); 878ce9adaa5SChris Mason spin_unlock_irqrestore(&fs_info->end_io_work_lock, flags); 879ce9adaa5SChris Mason 880ce9adaa5SChris Mason end_io_wq = list_entry(next, struct end_io_wq, list); 881ce9adaa5SChris Mason 882ce9adaa5SChris Mason bio = end_io_wq->bio; 883ce9adaa5SChris Mason if (!bio_ready_for_csum(bio)) { 884ce9adaa5SChris Mason spin_lock_irqsave(&fs_info->end_io_work_lock, flags); 885ce9adaa5SChris Mason was_empty = list_empty(&fs_info->end_io_work_list); 886ce9adaa5SChris Mason list_add_tail(&end_io_wq->list, 887ce9adaa5SChris Mason &fs_info->end_io_work_list); 888ce9adaa5SChris Mason spin_unlock_irqrestore(&fs_info->end_io_work_lock, 889ce9adaa5SChris Mason flags); 890ce9adaa5SChris Mason if (was_empty) 891ce9adaa5SChris Mason return; 892ce9adaa5SChris Mason continue; 893ce9adaa5SChris Mason } 894ce9adaa5SChris Mason error = end_io_wq->error; 895ce9adaa5SChris Mason bio->bi_private = end_io_wq->private; 896ce9adaa5SChris Mason bio->bi_end_io = end_io_wq->end_io; 897ce9adaa5SChris Mason kfree(end_io_wq); 898ce9adaa5SChris Mason bio_endio(bio, error); 899ce9adaa5SChris Mason } 900ce9adaa5SChris Mason } 901ce9adaa5SChris Mason 902ce9adaa5SChris Mason 9038a4b83ccSChris Mason struct btrfs_root *open_ctree(struct super_block *sb, 9048a4b83ccSChris Mason struct btrfs_fs_devices *fs_devices) 905eb60ceacSChris Mason { 906db94535dSChris Mason u32 sectorsize; 907db94535dSChris Mason u32 nodesize; 908db94535dSChris Mason u32 leafsize; 909db94535dSChris Mason u32 blocksize; 91087ee04ebSChris Mason u32 stripesize; 911e20d96d6SChris Mason struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 912e20d96d6SChris Mason GFP_NOFS); 913e20d96d6SChris Mason struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 914e20d96d6SChris Mason GFP_NOFS); 9158790d502SChris Mason struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info), 916e20d96d6SChris Mason GFP_NOFS); 9170b86a832SChris Mason struct btrfs_root *chunk_root = kmalloc(sizeof(struct btrfs_root), 9180b86a832SChris Mason GFP_NOFS); 9190b86a832SChris Mason struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root), 9200b86a832SChris Mason GFP_NOFS); 921eb60ceacSChris Mason int ret; 922e58ca020SYan int err = -EINVAL; 9232c90e5d6SChris Mason struct btrfs_super_block *disk_super; 9248790d502SChris Mason 92539279cc3SChris Mason if (!extent_root || !tree_root || !fs_info) { 92639279cc3SChris Mason err = -ENOMEM; 92739279cc3SChris Mason goto fail; 92839279cc3SChris Mason } 929ce9adaa5SChris Mason end_io_workqueue = create_workqueue("btrfs-end-io"); 930ce9adaa5SChris Mason BUG_ON(!end_io_workqueue); 931ce9adaa5SChris Mason 9320f7d52f4SChris Mason INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); 9338fd17795SChris Mason INIT_LIST_HEAD(&fs_info->trans_list); 934facda1e7SChris Mason INIT_LIST_HEAD(&fs_info->dead_roots); 93519c00ddcSChris Mason INIT_LIST_HEAD(&fs_info->hashers); 936ce9adaa5SChris Mason INIT_LIST_HEAD(&fs_info->end_io_work_list); 93719c00ddcSChris Mason spin_lock_init(&fs_info->hash_lock); 938ce9adaa5SChris Mason spin_lock_init(&fs_info->end_io_work_lock); 9391832a6d5SChris Mason spin_lock_init(&fs_info->delalloc_lock); 940cee36a03SChris Mason spin_lock_init(&fs_info->new_trans_lock); 94119c00ddcSChris Mason 94258176a96SJosef Bacik init_completion(&fs_info->kobj_unregister); 9432c90e5d6SChris Mason sb_set_blocksize(sb, 4096); 9449f5fae2fSChris Mason fs_info->tree_root = tree_root; 9459f5fae2fSChris Mason fs_info->extent_root = extent_root; 9460b86a832SChris Mason fs_info->chunk_root = chunk_root; 9470b86a832SChris Mason fs_info->dev_root = dev_root; 9488a4b83ccSChris Mason fs_info->fs_devices = fs_devices; 9490b86a832SChris Mason INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); 9506324fbf3SChris Mason INIT_LIST_HEAD(&fs_info->space_info); 9510b86a832SChris Mason btrfs_mapping_init(&fs_info->mapping_tree); 952e20d96d6SChris Mason fs_info->sb = sb; 953c59f8951SChris Mason fs_info->max_extent = (u64)-1; 9546f568d35SChris Mason fs_info->max_inline = 8192 * 1024; 95504160088SChris Mason setup_bdi(fs_info, &fs_info->bdi); 956d98237b3SChris Mason fs_info->btree_inode = new_inode(sb); 957d98237b3SChris Mason fs_info->btree_inode->i_ino = 1; 9582c90e5d6SChris Mason fs_info->btree_inode->i_nlink = 1; 959d98237b3SChris Mason fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 960d98237b3SChris Mason fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 96104160088SChris Mason fs_info->btree_inode->i_mapping->backing_dev_info = &fs_info->bdi; 96204160088SChris Mason 963d1310b2eSChris Mason extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree, 9645f39d397SChris Mason fs_info->btree_inode->i_mapping, 9655f39d397SChris Mason GFP_NOFS); 966d1310b2eSChris Mason extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree, 967d1310b2eSChris Mason GFP_NOFS); 9680da5468fSChris Mason 969d1310b2eSChris Mason BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; 970d1310b2eSChris Mason 971d1310b2eSChris Mason extent_io_tree_init(&fs_info->free_space_cache, 972f510cfecSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 973d1310b2eSChris Mason extent_io_tree_init(&fs_info->block_group_cache, 97496b5179dSChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 975d1310b2eSChris Mason extent_io_tree_init(&fs_info->pinned_extents, 9761a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 977d1310b2eSChris Mason extent_io_tree_init(&fs_info->pending_del, 9781a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 979d1310b2eSChris Mason extent_io_tree_init(&fs_info->extent_ins, 9801a5bc167SChris Mason fs_info->btree_inode->i_mapping, GFP_NOFS); 981e66f709bSChris Mason fs_info->do_barriers = 1; 982e18e4809SChris Mason 983ce9adaa5SChris Mason INIT_WORK(&fs_info->end_io_work, btrfs_end_io_csum); 9846da6abaeSChris Mason #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) 9856da6abaeSChris Mason INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); 9866da6abaeSChris Mason #else 98708607c1bSChris Mason INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 9886da6abaeSChris Mason #endif 9890f7d52f4SChris Mason BTRFS_I(fs_info->btree_inode)->root = tree_root; 9900f7d52f4SChris Mason memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 9910f7d52f4SChris Mason sizeof(struct btrfs_key)); 99222b0ebdaSChris Mason insert_inode_hash(fs_info->btree_inode); 993d98237b3SChris Mason mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 99439279cc3SChris Mason 99579154b1bSChris Mason mutex_init(&fs_info->trans_mutex); 996d561c025SChris Mason mutex_init(&fs_info->fs_mutex); 9973768f368SChris Mason 99819c00ddcSChris Mason #if 0 99919c00ddcSChris Mason ret = add_hasher(fs_info, "crc32c"); 100019c00ddcSChris Mason if (ret) { 100119c00ddcSChris Mason printk("btrfs: failed hash setup, modprobe cryptomgr?\n"); 100219c00ddcSChris Mason err = -ENOMEM; 100319c00ddcSChris Mason goto fail_iput; 100419c00ddcSChris Mason } 100519c00ddcSChris Mason #endif 10060b86a832SChris Mason __setup_root(4096, 4096, 4096, 4096, tree_root, 10072c90e5d6SChris Mason fs_info, BTRFS_ROOT_TREE_OBJECTID); 10087eccb903SChris Mason 10092c90e5d6SChris Mason fs_info->sb_buffer = read_tree_block(tree_root, 1010db94535dSChris Mason BTRFS_SUPER_INFO_OFFSET, 10110b86a832SChris Mason 4096); 1012d98237b3SChris Mason 10130f7d52f4SChris Mason if (!fs_info->sb_buffer) 101439279cc3SChris Mason goto fail_iput; 101539279cc3SChris Mason 10165f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, 10175f39d397SChris Mason sizeof(fs_info->super_copy)); 10185f39d397SChris Mason 10195f39d397SChris Mason read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, 10205f39d397SChris Mason (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), 10215f39d397SChris Mason BTRFS_FSID_SIZE); 10220b86a832SChris Mason 10235f39d397SChris Mason disk_super = &fs_info->super_copy; 10240f7d52f4SChris Mason if (!btrfs_super_root(disk_super)) 102539279cc3SChris Mason goto fail_sb_buffer; 10260f7d52f4SChris Mason 10278a4b83ccSChris Mason if (btrfs_super_num_devices(disk_super) != fs_devices->num_devices) { 10288a4b83ccSChris Mason printk("Btrfs: wanted %llu devices, but found %llu\n", 10298a4b83ccSChris Mason (unsigned long long)btrfs_super_num_devices(disk_super), 10308a4b83ccSChris Mason (unsigned long long)fs_devices->num_devices); 10318a4b83ccSChris Mason goto fail_sb_buffer; 10328a4b83ccSChris Mason } 1033db94535dSChris Mason nodesize = btrfs_super_nodesize(disk_super); 1034db94535dSChris Mason leafsize = btrfs_super_leafsize(disk_super); 1035db94535dSChris Mason sectorsize = btrfs_super_sectorsize(disk_super); 103687ee04ebSChris Mason stripesize = btrfs_super_stripesize(disk_super); 1037db94535dSChris Mason tree_root->nodesize = nodesize; 1038db94535dSChris Mason tree_root->leafsize = leafsize; 1039db94535dSChris Mason tree_root->sectorsize = sectorsize; 104087ee04ebSChris Mason tree_root->stripesize = stripesize; 1041ff79f819SChris Mason sb_set_blocksize(sb, sectorsize); 1042db94535dSChris Mason 10438352d8a4SChris Mason i_size_write(fs_info->btree_inode, 1044db94535dSChris Mason btrfs_super_total_bytes(disk_super)); 10458352d8a4SChris Mason 104639279cc3SChris Mason if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, 104739279cc3SChris Mason sizeof(disk_super->magic))) { 104839279cc3SChris Mason printk("btrfs: valid FS not found on %s\n", sb->s_id); 104939279cc3SChris Mason goto fail_sb_buffer; 105039279cc3SChris Mason } 105119c00ddcSChris Mason 10520b86a832SChris Mason mutex_lock(&fs_info->fs_mutex); 10530d81ba5dSChris Mason 10540b86a832SChris Mason ret = btrfs_read_sys_array(tree_root); 10550b86a832SChris Mason BUG_ON(ret); 10560b86a832SChris Mason 10570b86a832SChris Mason blocksize = btrfs_level_size(tree_root, 10580b86a832SChris Mason btrfs_super_chunk_root_level(disk_super)); 10590b86a832SChris Mason 10600b86a832SChris Mason __setup_root(nodesize, leafsize, sectorsize, stripesize, 10610b86a832SChris Mason chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); 10620b86a832SChris Mason 10630b86a832SChris Mason chunk_root->node = read_tree_block(chunk_root, 10640b86a832SChris Mason btrfs_super_chunk_root(disk_super), 10650b86a832SChris Mason blocksize); 10660b86a832SChris Mason BUG_ON(!chunk_root->node); 10670b86a832SChris Mason 10680b86a832SChris Mason ret = btrfs_read_chunk_tree(chunk_root); 10690b86a832SChris Mason BUG_ON(ret); 10700b86a832SChris Mason 1071db94535dSChris Mason blocksize = btrfs_level_size(tree_root, 1072db94535dSChris Mason btrfs_super_root_level(disk_super)); 107319c00ddcSChris Mason 10740b86a832SChris Mason 1075e20d96d6SChris Mason tree_root->node = read_tree_block(tree_root, 1076db94535dSChris Mason btrfs_super_root(disk_super), 1077db94535dSChris Mason blocksize); 107839279cc3SChris Mason if (!tree_root->node) 107939279cc3SChris Mason goto fail_sb_buffer; 10803768f368SChris Mason 1081db94535dSChris Mason 1082db94535dSChris Mason ret = find_and_setup_root(tree_root, fs_info, 1083e20d96d6SChris Mason BTRFS_EXTENT_TREE_OBJECTID, extent_root); 10840b86a832SChris Mason if (ret) 108539279cc3SChris Mason goto fail_tree_root; 10860b86a832SChris Mason extent_root->track_dirty = 1; 10870b86a832SChris Mason 10880b86a832SChris Mason ret = find_and_setup_root(tree_root, fs_info, 10890b86a832SChris Mason BTRFS_DEV_TREE_OBJECTID, dev_root); 10900b86a832SChris Mason dev_root->track_dirty = 1; 10910b86a832SChris Mason 10920b86a832SChris Mason if (ret) 10930b86a832SChris Mason goto fail_extent_root; 10943768f368SChris Mason 10959078a3e1SChris Mason btrfs_read_block_groups(extent_root); 10969078a3e1SChris Mason 10970f7d52f4SChris Mason fs_info->generation = btrfs_super_generation(disk_super) + 1; 1098d18a2c44SChris Mason fs_info->data_alloc_profile = (u64)-1; 1099d18a2c44SChris Mason fs_info->metadata_alloc_profile = (u64)-1; 1100611f0e00SChris Mason fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; 1101d18a2c44SChris Mason 11025be6f7f1SChris Mason mutex_unlock(&fs_info->fs_mutex); 11030f7d52f4SChris Mason return tree_root; 110439279cc3SChris Mason 11050b86a832SChris Mason fail_extent_root: 11060b86a832SChris Mason free_extent_buffer(extent_root->node); 110739279cc3SChris Mason fail_tree_root: 11080b86a832SChris Mason mutex_unlock(&fs_info->fs_mutex); 11095f39d397SChris Mason free_extent_buffer(tree_root->node); 111039279cc3SChris Mason fail_sb_buffer: 11115f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 11122d2ae547SChris Mason extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); 111339279cc3SChris Mason fail_iput: 111439279cc3SChris Mason iput(fs_info->btree_inode); 111539279cc3SChris Mason fail: 11168a4b83ccSChris Mason close_all_devices(fs_info); 111739279cc3SChris Mason kfree(extent_root); 111839279cc3SChris Mason kfree(tree_root); 11192d2ae547SChris Mason bdi_destroy(&fs_info->bdi); 112039279cc3SChris Mason kfree(fs_info); 112139279cc3SChris Mason return ERR_PTR(err); 1122eb60ceacSChris Mason } 1123eb60ceacSChris Mason 1124e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 112579154b1bSChris Mason *root) 1126cfaa7295SChris Mason { 1127e66f709bSChris Mason int ret; 11285f39d397SChris Mason struct extent_buffer *super = root->fs_info->sb_buffer; 11295f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 113021ad10cfSChris Mason struct super_block *sb = root->fs_info->sb; 11312c90e5d6SChris Mason 113221ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 113321ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 1134d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super); 11355f39d397SChris Mason ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, 11365f39d397SChris Mason super->start, super->len); 113721ad10cfSChris Mason if (!btrfs_test_opt(root, NOBARRIER)) 113821ad10cfSChris Mason blkdev_issue_flush(sb->s_bdev, NULL); 11395f39d397SChris Mason return ret; 1140cfaa7295SChris Mason } 1141cfaa7295SChris Mason 11425eda7b5eSChris Mason int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 11432619ba1fSChris Mason { 11442619ba1fSChris Mason radix_tree_delete(&fs_info->fs_roots_radix, 11452619ba1fSChris Mason (unsigned long)root->root_key.objectid); 1146b99aa6cbSChris Mason if (root->in_sysfs) 114758176a96SJosef Bacik btrfs_sysfs_del_root(root); 11482619ba1fSChris Mason if (root->inode) 11492619ba1fSChris Mason iput(root->inode); 11502619ba1fSChris Mason if (root->node) 11515f39d397SChris Mason free_extent_buffer(root->node); 11522619ba1fSChris Mason if (root->commit_root) 11535f39d397SChris Mason free_extent_buffer(root->commit_root); 115458176a96SJosef Bacik if (root->name) 115558176a96SJosef Bacik kfree(root->name); 11562619ba1fSChris Mason kfree(root); 11572619ba1fSChris Mason return 0; 11582619ba1fSChris Mason } 11592619ba1fSChris Mason 116035b7e476SChris Mason static int del_fs_roots(struct btrfs_fs_info *fs_info) 11610f7d52f4SChris Mason { 11620f7d52f4SChris Mason int ret; 11630f7d52f4SChris Mason struct btrfs_root *gang[8]; 11640f7d52f4SChris Mason int i; 11650f7d52f4SChris Mason 11660f7d52f4SChris Mason while(1) { 11670f7d52f4SChris Mason ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, 11680f7d52f4SChris Mason (void **)gang, 0, 11690f7d52f4SChris Mason ARRAY_SIZE(gang)); 11700f7d52f4SChris Mason if (!ret) 11710f7d52f4SChris Mason break; 11722619ba1fSChris Mason for (i = 0; i < ret; i++) 11735eda7b5eSChris Mason btrfs_free_fs_root(fs_info, gang[i]); 11740f7d52f4SChris Mason } 11750f7d52f4SChris Mason return 0; 11760f7d52f4SChris Mason } 1177b4100d64SChris Mason 1178e20d96d6SChris Mason int close_ctree(struct btrfs_root *root) 1179eb60ceacSChris Mason { 11803768f368SChris Mason int ret; 1181e089f05cSChris Mason struct btrfs_trans_handle *trans; 11820f7d52f4SChris Mason struct btrfs_fs_info *fs_info = root->fs_info; 1183e089f05cSChris Mason 1184facda1e7SChris Mason fs_info->closing = 1; 118508607c1bSChris Mason btrfs_transaction_flush_work(root); 11860f7d52f4SChris Mason mutex_lock(&fs_info->fs_mutex); 11876702ed49SChris Mason btrfs_defrag_dirty_roots(root->fs_info); 118879154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 118954aa1f4dSChris Mason ret = btrfs_commit_transaction(trans, root); 119079154b1bSChris Mason /* run commit again to drop the original snapshot */ 119179154b1bSChris Mason trans = btrfs_start_transaction(root, 1); 119279154b1bSChris Mason btrfs_commit_transaction(trans, root); 119379154b1bSChris Mason ret = btrfs_write_and_wait_transaction(NULL, root); 11949f5fae2fSChris Mason BUG_ON(ret); 119579154b1bSChris Mason write_ctree_super(NULL, root); 11960f7d52f4SChris Mason mutex_unlock(&fs_info->fs_mutex); 1197ed2ff2cbSChris Mason 1198b0c68f8bSChris Mason if (fs_info->delalloc_bytes) { 1199b0c68f8bSChris Mason printk("btrfs: at unmount delalloc count %Lu\n", 1200b0c68f8bSChris Mason fs_info->delalloc_bytes); 1201b0c68f8bSChris Mason } 12020f7d52f4SChris Mason if (fs_info->extent_root->node) 12035f39d397SChris Mason free_extent_buffer(fs_info->extent_root->node); 1204f510cfecSChris Mason 12050f7d52f4SChris Mason if (fs_info->tree_root->node) 12065f39d397SChris Mason free_extent_buffer(fs_info->tree_root->node); 1207f510cfecSChris Mason 12080b86a832SChris Mason if (root->fs_info->chunk_root->node); 12090b86a832SChris Mason free_extent_buffer(root->fs_info->chunk_root->node); 12100b86a832SChris Mason 12110b86a832SChris Mason if (root->fs_info->dev_root->node); 12120b86a832SChris Mason free_extent_buffer(root->fs_info->dev_root->node); 12130b86a832SChris Mason 12145f39d397SChris Mason free_extent_buffer(fs_info->sb_buffer); 12157eccb903SChris Mason 12169078a3e1SChris Mason btrfs_free_block_groups(root->fs_info); 12170f7d52f4SChris Mason del_fs_roots(fs_info); 1218d10c5f31SChris Mason 1219d10c5f31SChris Mason filemap_write_and_wait(fs_info->btree_inode->i_mapping); 1220d10c5f31SChris Mason 1221d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->free_space_cache); 1222d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->block_group_cache); 1223d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pinned_extents); 1224d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->pending_del); 1225d1310b2eSChris Mason extent_io_tree_empty_lru(&fs_info->extent_ins); 1226d1310b2eSChris Mason extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); 1227d10c5f31SChris Mason 1228db94535dSChris Mason truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); 1229ce9adaa5SChris Mason flush_workqueue(end_io_workqueue); 1230ce9adaa5SChris Mason destroy_workqueue(end_io_workqueue); 1231d10c5f31SChris Mason 1232db94535dSChris Mason iput(fs_info->btree_inode); 123319c00ddcSChris Mason #if 0 123419c00ddcSChris Mason while(!list_empty(&fs_info->hashers)) { 123519c00ddcSChris Mason struct btrfs_hasher *hasher; 123619c00ddcSChris Mason hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher, 123719c00ddcSChris Mason hashers); 123819c00ddcSChris Mason list_del(&hasher->hashers); 123919c00ddcSChris Mason crypto_free_hash(&fs_info->hash_tfm); 124019c00ddcSChris Mason kfree(hasher); 124119c00ddcSChris Mason } 124219c00ddcSChris Mason #endif 12430b86a832SChris Mason close_all_devices(fs_info); 12440b86a832SChris Mason btrfs_mapping_tree_free(&fs_info->mapping_tree); 124504160088SChris Mason bdi_destroy(&fs_info->bdi); 12460b86a832SChris Mason 12470f7d52f4SChris Mason kfree(fs_info->extent_root); 12480f7d52f4SChris Mason kfree(fs_info->tree_root); 12490b86a832SChris Mason kfree(fs_info->chunk_root); 12500b86a832SChris Mason kfree(fs_info->dev_root); 1251eb60ceacSChris Mason return 0; 1252eb60ceacSChris Mason } 1253eb60ceacSChris Mason 12545f39d397SChris Mason int btrfs_buffer_uptodate(struct extent_buffer *buf) 1255ccd467d6SChris Mason { 1256810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 1257d1310b2eSChris Mason return extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); 12585f39d397SChris Mason } 12596702ed49SChris Mason 12605f39d397SChris Mason int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 12615f39d397SChris Mason { 1262810191ffSChris Mason struct inode *btree_inode = buf->first_page->mapping->host; 1263d1310b2eSChris Mason return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, 12645f39d397SChris Mason buf); 12655f39d397SChris Mason } 12665f39d397SChris Mason 12675f39d397SChris Mason void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 12685f39d397SChris Mason { 1269810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 12705f39d397SChris Mason u64 transid = btrfs_header_generation(buf); 12715f39d397SChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 12726702ed49SChris Mason 1273ccd467d6SChris Mason if (transid != root->fs_info->generation) { 1274ccd467d6SChris Mason printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", 1275db94535dSChris Mason (unsigned long long)buf->start, 1276ccd467d6SChris Mason transid, root->fs_info->generation); 1277ccd467d6SChris Mason WARN_ON(1); 1278ccd467d6SChris Mason } 1279d1310b2eSChris Mason set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); 1280eb60ceacSChris Mason } 1281eb60ceacSChris Mason 1282e2008b61SChris Mason void btrfs_throttle(struct btrfs_root *root) 1283e2008b61SChris Mason { 128455c69072SChris Mason struct backing_dev_info *bdi; 128555c69072SChris Mason 128655c69072SChris Mason bdi = root->fs_info->sb->s_bdev->bd_inode->i_mapping->backing_dev_info; 128704005cc7SChris Mason if (root->fs_info->throttles && bdi_write_congested(bdi)) { 128804005cc7SChris Mason #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) 128955c69072SChris Mason congestion_wait(WRITE, HZ/20); 129004005cc7SChris Mason #else 129104005cc7SChris Mason blk_congestion_wait(WRITE, HZ/20); 129204005cc7SChris Mason #endif 129304005cc7SChris Mason } 1294e2008b61SChris Mason } 1295e2008b61SChris Mason 1296d3c2fdcfSChris Mason void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) 129735b7e476SChris Mason { 1298d3c2fdcfSChris Mason balance_dirty_pages_ratelimited_nr( 1299304fced6SChris Mason root->fs_info->btree_inode->i_mapping, 1); 130035b7e476SChris Mason } 13016b80053dSChris Mason 13026b80053dSChris Mason void btrfs_set_buffer_defrag(struct extent_buffer *buf) 13036b80053dSChris Mason { 1304810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13056b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1306d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 13076b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 13086b80053dSChris Mason } 13096b80053dSChris Mason 13106b80053dSChris Mason void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 13116b80053dSChris Mason { 1312810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13136b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1314d1310b2eSChris Mason set_extent_bits(&BTRFS_I(btree_inode)->io_tree, buf->start, 13156b80053dSChris Mason buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 13166b80053dSChris Mason GFP_NOFS); 13176b80053dSChris Mason } 13186b80053dSChris Mason 13196b80053dSChris Mason int btrfs_buffer_defrag(struct extent_buffer *buf) 13206b80053dSChris Mason { 1321810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13226b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1323d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 13246b80053dSChris Mason buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 13256b80053dSChris Mason } 13266b80053dSChris Mason 13276b80053dSChris Mason int btrfs_buffer_defrag_done(struct extent_buffer *buf) 13286b80053dSChris Mason { 1329810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13306b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1331d1310b2eSChris Mason return test_range_bit(&BTRFS_I(btree_inode)->io_tree, 13326b80053dSChris Mason buf->start, buf->start + buf->len - 1, 13336b80053dSChris Mason EXTENT_DEFRAG_DONE, 0); 13346b80053dSChris Mason } 13356b80053dSChris Mason 13366b80053dSChris Mason int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 13376b80053dSChris Mason { 1338810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13396b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1340d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 13416b80053dSChris Mason buf->start, buf->start + buf->len - 1, 13426b80053dSChris Mason EXTENT_DEFRAG_DONE, GFP_NOFS); 13436b80053dSChris Mason } 13446b80053dSChris Mason 13456b80053dSChris Mason int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 13466b80053dSChris Mason { 1347810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13486b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1349d1310b2eSChris Mason return clear_extent_bits(&BTRFS_I(btree_inode)->io_tree, 13506b80053dSChris Mason buf->start, buf->start + buf->len - 1, 13516b80053dSChris Mason EXTENT_DEFRAG, GFP_NOFS); 13526b80053dSChris Mason } 13536b80053dSChris Mason 13546b80053dSChris Mason int btrfs_read_buffer(struct extent_buffer *buf) 13556b80053dSChris Mason { 1356810191ffSChris Mason struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; 13576b80053dSChris Mason struct inode *btree_inode = root->fs_info->btree_inode; 1358ce9adaa5SChris Mason int ret; 1359ce9adaa5SChris Mason ret = read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, 1360a86c12c7SChris Mason buf, 0, 1, btree_get_extent); 1361ce9adaa5SChris Mason if (ret == 0) { 1362ce9adaa5SChris Mason buf->flags |= EXTENT_UPTODATE; 1363ce9adaa5SChris Mason } 1364ce9adaa5SChris Mason return ret; 13656b80053dSChris Mason } 13660da5468fSChris Mason 1367d1310b2eSChris Mason static struct extent_io_ops btree_extent_io_ops = { 13680da5468fSChris Mason .writepage_io_hook = btree_writepage_io_hook, 1369ce9adaa5SChris Mason .readpage_end_io_hook = btree_readpage_end_io_hook, 13700b86a832SChris Mason .submit_bio_hook = btree_submit_bio_hook, 1371239b14b3SChris Mason /* note we're sharing with inode.c for the merge bio hook */ 1372239b14b3SChris Mason .merge_bio_hook = btrfs_merge_bio_hook, 13730da5468fSChris Mason }; 1374