aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-04-11 20:46:03 -0400
committerChris Mason <chris.mason@oracle.com>2011-04-11 20:46:03 -0400
commit874d0d2633e0f3fe955607c6b04d5fc5325781c4 (patch)
treea96165f1f13501419af1c88dae146bc1061f8664 /fs/btrfs/inode.c
parent507903b81840a70cc6a179d4eb03584ad50e8c5b (diff)
parent13c5a93e7005d7dae0b6d070d25203593e692d13 (diff)
Merge branch 'for-chris' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-work into for-linus
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c107
1 files changed, 82 insertions, 25 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5a993e0ec865..55a6a0b416d7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1769,9 +1769,12 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1769 add_pending_csums(trans, inode, ordered_extent->file_offset, 1769 add_pending_csums(trans, inode, ordered_extent->file_offset,
1770 &ordered_extent->list); 1770 &ordered_extent->list);
1771 1771
1772 btrfs_ordered_update_i_size(inode, 0, ordered_extent); 1772 ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
1773 ret = btrfs_update_inode(trans, root, inode); 1773 if (!ret) {
1774 BUG_ON(ret); 1774 ret = btrfs_update_inode(trans, root, inode);
1775 BUG_ON(ret);
1776 }
1777 ret = 0;
1775out: 1778out:
1776 if (nolock) { 1779 if (nolock) {
1777 if (trans) 1780 if (trans)
@@ -2589,6 +2592,13 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
2589 struct btrfs_inode_item *item, 2592 struct btrfs_inode_item *item,
2590 struct inode *inode) 2593 struct inode *inode)
2591{ 2594{
2595 if (!leaf->map_token)
2596 map_private_extent_buffer(leaf, (unsigned long)item,
2597 sizeof(struct btrfs_inode_item),
2598 &leaf->map_token, &leaf->kaddr,
2599 &leaf->map_start, &leaf->map_len,
2600 KM_USER1);
2601
2592 btrfs_set_inode_uid(leaf, item, inode->i_uid); 2602 btrfs_set_inode_uid(leaf, item, inode->i_uid);
2593 btrfs_set_inode_gid(leaf, item, inode->i_gid); 2603 btrfs_set_inode_gid(leaf, item, inode->i_gid);
2594 btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size); 2604 btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size);
@@ -2617,6 +2627,11 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
2617 btrfs_set_inode_rdev(leaf, item, inode->i_rdev); 2627 btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
2618 btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); 2628 btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
2619 btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); 2629 btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group);
2630
2631 if (leaf->map_token) {
2632 unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
2633 leaf->map_token = NULL;
2634 }
2620} 2635}
2621 2636
2622/* 2637/*
@@ -5433,17 +5448,30 @@ out:
5433} 5448}
5434 5449
5435static struct extent_map *btrfs_new_extent_direct(struct inode *inode, 5450static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5451 struct extent_map *em,
5436 u64 start, u64 len) 5452 u64 start, u64 len)
5437{ 5453{
5438 struct btrfs_root *root = BTRFS_I(inode)->root; 5454 struct btrfs_root *root = BTRFS_I(inode)->root;
5439 struct btrfs_trans_handle *trans; 5455 struct btrfs_trans_handle *trans;
5440 struct extent_map *em;
5441 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 5456 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
5442 struct btrfs_key ins; 5457 struct btrfs_key ins;
5443 u64 alloc_hint; 5458 u64 alloc_hint;
5444 int ret; 5459 int ret;
5460 bool insert = false;
5445 5461
5446 btrfs_drop_extent_cache(inode, start, start + len - 1, 0); 5462 /*
5463 * Ok if the extent map we looked up is a hole and is for the exact
5464 * range we want, there is no reason to allocate a new one, however if
5465 * it is not right then we need to free this one and drop the cache for
5466 * our range.
5467 */
5468 if (em->block_start != EXTENT_MAP_HOLE || em->start != start ||
5469 em->len != len) {
5470 free_extent_map(em);
5471 em = NULL;
5472 insert = true;
5473 btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
5474 }
5447 5475
5448 trans = btrfs_join_transaction(root, 0); 5476 trans = btrfs_join_transaction(root, 0);
5449 if (IS_ERR(trans)) 5477 if (IS_ERR(trans))
@@ -5459,10 +5487,12 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5459 goto out; 5487 goto out;
5460 } 5488 }
5461 5489
5462 em = alloc_extent_map(GFP_NOFS);
5463 if (!em) { 5490 if (!em) {
5464 em = ERR_PTR(-ENOMEM); 5491 em = alloc_extent_map(GFP_NOFS);
5465 goto out; 5492 if (!em) {
5493 em = ERR_PTR(-ENOMEM);
5494 goto out;
5495 }
5466 } 5496 }
5467 5497
5468 em->start = start; 5498 em->start = start;
@@ -5472,9 +5502,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5472 em->block_start = ins.objectid; 5502 em->block_start = ins.objectid;
5473 em->block_len = ins.offset; 5503 em->block_len = ins.offset;
5474 em->bdev = root->fs_info->fs_devices->latest_bdev; 5504 em->bdev = root->fs_info->fs_devices->latest_bdev;
5505
5506 /*
5507 * We need to do this because if we're using the original em we searched
5508 * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that.
5509 */
5510 em->flags = 0;
5475 set_bit(EXTENT_FLAG_PINNED, &em->flags); 5511 set_bit(EXTENT_FLAG_PINNED, &em->flags);
5476 5512
5477 while (1) { 5513 while (insert) {
5478 write_lock(&em_tree->lock); 5514 write_lock(&em_tree->lock);
5479 ret = add_extent_mapping(em_tree, em); 5515 ret = add_extent_mapping(em_tree, em);
5480 write_unlock(&em_tree->lock); 5516 write_unlock(&em_tree->lock);
@@ -5692,8 +5728,7 @@ must_cow:
5692 * it above 5728 * it above
5693 */ 5729 */
5694 len = bh_result->b_size; 5730 len = bh_result->b_size;
5695 free_extent_map(em); 5731 em = btrfs_new_extent_direct(inode, em, start, len);
5696 em = btrfs_new_extent_direct(inode, start, len);
5697 if (IS_ERR(em)) 5732 if (IS_ERR(em))
5698 return PTR_ERR(em); 5733 return PTR_ERR(em);
5699 len = min(len, em->len - (start - em->start)); 5734 len = min(len, em->len - (start - em->start));
@@ -5856,8 +5891,10 @@ again:
5856 } 5891 }
5857 5892
5858 add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); 5893 add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
5859 btrfs_ordered_update_i_size(inode, 0, ordered); 5894 ret = btrfs_ordered_update_i_size(inode, 0, ordered);
5860 btrfs_update_inode(trans, root, inode); 5895 if (!ret)
5896 btrfs_update_inode(trans, root, inode);
5897 ret = 0;
5861out_unlock: 5898out_unlock:
5862 unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, 5899 unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset,
5863 ordered->file_offset + ordered->len - 1, 5900 ordered->file_offset + ordered->len - 1,
@@ -5943,7 +5980,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
5943 5980
5944static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, 5981static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
5945 int rw, u64 file_offset, int skip_sum, 5982 int rw, u64 file_offset, int skip_sum,
5946 u32 *csums) 5983 u32 *csums, int async_submit)
5947{ 5984{
5948 int write = rw & REQ_WRITE; 5985 int write = rw & REQ_WRITE;
5949 struct btrfs_root *root = BTRFS_I(inode)->root; 5986 struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -5954,13 +5991,24 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
5954 if (ret) 5991 if (ret)
5955 goto err; 5992 goto err;
5956 5993
5957 if (write && !skip_sum) { 5994 if (skip_sum)
5995 goto map;
5996
5997 if (write && async_submit) {
5958 ret = btrfs_wq_submit_bio(root->fs_info, 5998 ret = btrfs_wq_submit_bio(root->fs_info,
5959 inode, rw, bio, 0, 0, 5999 inode, rw, bio, 0, 0,
5960 file_offset, 6000 file_offset,
5961 __btrfs_submit_bio_start_direct_io, 6001 __btrfs_submit_bio_start_direct_io,
5962 __btrfs_submit_bio_done); 6002 __btrfs_submit_bio_done);
5963 goto err; 6003 goto err;
6004 } else if (write) {
6005 /*
6006 * If we aren't doing async submit, calculate the csum of the
6007 * bio now.
6008 */
6009 ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1);
6010 if (ret)
6011 goto err;
5964 } else if (!skip_sum) { 6012 } else if (!skip_sum) {
5965 ret = btrfs_lookup_bio_sums_dio(root, inode, bio, 6013 ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
5966 file_offset, csums); 6014 file_offset, csums);
@@ -5968,7 +6016,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
5968 goto err; 6016 goto err;
5969 } 6017 }
5970 6018
5971 ret = btrfs_map_bio(root, rw, bio, 0, 1); 6019map:
6020 ret = btrfs_map_bio(root, rw, bio, 0, async_submit);
5972err: 6021err:
5973 bio_put(bio); 6022 bio_put(bio);
5974 return ret; 6023 return ret;
@@ -5990,15 +6039,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
5990 int nr_pages = 0; 6039 int nr_pages = 0;
5991 u32 *csums = dip->csums; 6040 u32 *csums = dip->csums;
5992 int ret = 0; 6041 int ret = 0;
6042 int async_submit = 0;
5993 int write = rw & REQ_WRITE; 6043 int write = rw & REQ_WRITE;
5994 6044
5995 bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
5996 if (!bio)
5997 return -ENOMEM;
5998 bio->bi_private = dip;
5999 bio->bi_end_io = btrfs_end_dio_bio;
6000 atomic_inc(&dip->pending_bios);
6001
6002 map_length = orig_bio->bi_size; 6045 map_length = orig_bio->bi_size;
6003 ret = btrfs_map_block(map_tree, READ, start_sector << 9, 6046 ret = btrfs_map_block(map_tree, READ, start_sector << 9,
6004 &map_length, NULL, 0); 6047 &map_length, NULL, 0);
@@ -6007,6 +6050,19 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6007 return -EIO; 6050 return -EIO;
6008 } 6051 }
6009 6052
6053 if (map_length >= orig_bio->bi_size) {
6054 bio = orig_bio;
6055 goto submit;
6056 }
6057
6058 async_submit = 1;
6059 bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
6060 if (!bio)
6061 return -ENOMEM;
6062 bio->bi_private = dip;
6063 bio->bi_end_io = btrfs_end_dio_bio;
6064 atomic_inc(&dip->pending_bios);
6065
6010 while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { 6066 while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
6011 if (unlikely(map_length < submit_len + bvec->bv_len || 6067 if (unlikely(map_length < submit_len + bvec->bv_len ||
6012 bio_add_page(bio, bvec->bv_page, bvec->bv_len, 6068 bio_add_page(bio, bvec->bv_page, bvec->bv_len,
@@ -6020,7 +6076,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6020 atomic_inc(&dip->pending_bios); 6076 atomic_inc(&dip->pending_bios);
6021 ret = __btrfs_submit_dio_bio(bio, inode, rw, 6077 ret = __btrfs_submit_dio_bio(bio, inode, rw,
6022 file_offset, skip_sum, 6078 file_offset, skip_sum,
6023 csums); 6079 csums, async_submit);
6024 if (ret) { 6080 if (ret) {
6025 bio_put(bio); 6081 bio_put(bio);
6026 atomic_dec(&dip->pending_bios); 6082 atomic_dec(&dip->pending_bios);
@@ -6057,8 +6113,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6057 } 6113 }
6058 } 6114 }
6059 6115
6116submit:
6060 ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, 6117 ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
6061 csums); 6118 csums, async_submit);
6062 if (!ret) 6119 if (!ret)
6063 return 0; 6120 return 0;
6064 6121