aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-11-04 19:56:02 -0400
committerChris Mason <chris.mason@oracle.com>2011-11-06 03:04:20 -0500
commitc06a0e120a4e381a1c291c1fce3c6155c5791cae (patch)
treea9d1c44610b37c701d25e439b005dacfa0f823c1 /fs
parentbf0da8c183a15656eee63c54f334c3794320872a (diff)
Btrfs: fix delayed insertion reservation
We all keep getting those stupid warnings from use_block_rsv when running stress.sh, and it's because the delayed insertion stuff is being stupid. It's not the delayed insertion stuffs fault, it's all just stupid. When marking an inode dirty for oh say updating the time on it, we just do a btrfs_join_transaction, which doesn't reserve any space. This is stupid because we're going to have to have space reserve to make this change, but we do it because it's fast because chances are we're going to call it over and over again and it doesn't matter. Well thanks to the delayed insertion stuff this is mostly the case, so we do actually need to make this reservation. So if trans->bytes_reserved is 0 then try to do a normal reservation. If not return ENOSPC which will make the btrfs_dirty_inode start a proper transaction which will let it do the whole ENOSPC dance and reserve enough space for the delayed insertion to steal the reservation from the transaction. The other stupid thing we do is not reserve space for the inode when writing to the thing. Usually this is ok since we have to update the time so we'd have already done all this work before we get to the endio stuff, so it doesn't matter. But this is stupid because we could write the data after the transaction commits where we changed the mtime of the inode so we have to cow all the way down to the inode anyway. This used to be masked by the delalloc reservation stuff, but because we delay the update it doesn't get masked in this case. So again the delayed insertion stuff bites us in the ass. So if our trans->block_rsv is delalloc, just steal the reservation from the delalloc reserve. Hopefully this won't bite us in the ass, but I've said that before. With this patch stress.sh no longer spits out those stupid warnings (famous last words). Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/delayed-inode.c36
-rw-r--r--fs/btrfs/extent-tree.c18
3 files changed, 49 insertions, 8 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3002e5d4da0b..6bb34fc1ff22 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2353,6 +2353,9 @@ void btrfs_free_block_rsv(struct btrfs_root *root,
2353int btrfs_block_rsv_add(struct btrfs_root *root, 2353int btrfs_block_rsv_add(struct btrfs_root *root,
2354 struct btrfs_block_rsv *block_rsv, 2354 struct btrfs_block_rsv *block_rsv,
2355 u64 num_bytes); 2355 u64 num_bytes);
2356int btrfs_block_rsv_add_noflush(struct btrfs_root *root,
2357 struct btrfs_block_rsv *block_rsv,
2358 u64 num_bytes);
2356int btrfs_block_rsv_check(struct btrfs_root *root, 2359int btrfs_block_rsv_check(struct btrfs_root *root,
2357 struct btrfs_block_rsv *block_rsv, int min_factor); 2360 struct btrfs_block_rsv *block_rsv, int min_factor);
2358int btrfs_block_rsv_refill(struct btrfs_root *root, 2361int btrfs_block_rsv_refill(struct btrfs_root *root,
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index fc4026af7290..bbe8496d5339 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -624,13 +624,36 @@ static int btrfs_delayed_inode_reserve_metadata(
624 u64 num_bytes; 624 u64 num_bytes;
625 int ret; 625 int ret;
626 626
627 if (!trans->bytes_reserved)
628 return 0;
629
630 src_rsv = trans->block_rsv; 627 src_rsv = trans->block_rsv;
631 dst_rsv = &root->fs_info->delayed_block_rsv; 628 dst_rsv = &root->fs_info->delayed_block_rsv;
632 629
633 num_bytes = btrfs_calc_trans_metadata_size(root, 1); 630 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
631
632 /*
633 * btrfs_dirty_inode will update the inode under btrfs_join_transaction
634 * which doesn't reserve space for speed. This is a problem since we
635 * still need to reserve space for this update, so try to reserve the
636 * space.
637 *
638 * Now if src_rsv == delalloc_block_rsv we'll let it just steal since
639 * we're accounted for.
640 */
641 if (!trans->bytes_reserved &&
642 src_rsv != &root->fs_info->delalloc_block_rsv) {
643 ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes);
644 /*
645 * Since we're under a transaction reserve_metadata_bytes could
646 * try to commit the transaction which will make it return
647 * EAGAIN to make us stop the transaction we have, so return
648 * ENOSPC instead so that btrfs_dirty_inode knows what to do.
649 */
650 if (ret == -EAGAIN)
651 ret = -ENOSPC;
652 if (!ret)
653 node->bytes_reserved = num_bytes;
654 return ret;
655 }
656
634 ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); 657 ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
635 if (!ret) 658 if (!ret)
636 node->bytes_reserved = num_bytes; 659 node->bytes_reserved = num_bytes;
@@ -1686,11 +1709,8 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
1686 } 1709 }
1687 1710
1688 ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node); 1711 ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node);
1689 /* 1712 if (ret)
1690 * we must reserve enough space when we start a new transaction, 1713 goto release_node;
1691 * so reserving metadata failure is impossible
1692 */
1693 BUG_ON(ret);
1694 1714
1695 fill_stack_inode_item(trans, &delayed_node->inode_item, inode); 1715 fill_stack_inode_item(trans, &delayed_node->inode_item, inode);
1696 delayed_node->inode_dirty = 1; 1716 delayed_node->inode_dirty = 1;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5b84205e7685..23e936c3de76 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3814,6 +3814,24 @@ int btrfs_block_rsv_add(struct btrfs_root *root,
3814 return ret; 3814 return ret;
3815} 3815}
3816 3816
3817int btrfs_block_rsv_add_noflush(struct btrfs_root *root,
3818 struct btrfs_block_rsv *block_rsv,
3819 u64 num_bytes)
3820{
3821 int ret;
3822
3823 if (num_bytes == 0)
3824 return 0;
3825
3826 ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 0);
3827 if (!ret) {
3828 block_rsv_add_bytes(block_rsv, num_bytes, 1);
3829 return 0;
3830 }
3831
3832 return ret;
3833}
3834
3817int btrfs_block_rsv_check(struct btrfs_root *root, 3835int btrfs_block_rsv_check(struct btrfs_root *root,
3818 struct btrfs_block_rsv *block_rsv, int min_factor) 3836 struct btrfs_block_rsv *block_rsv, int min_factor)
3819{ 3837{