aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/extent-tree.c42
-rw-r--r--fs/btrfs/inode.c5
3 files changed, 29 insertions, 21 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index ccc991c542df..57c3bb2884ce 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -136,9 +136,8 @@ struct btrfs_inode {
136 * items we think we'll end up using, and reserved_extents is the number 136 * items we think we'll end up using, and reserved_extents is the number
137 * of extent items we've reserved metadata for. 137 * of extent items we've reserved metadata for.
138 */ 138 */
139 spinlock_t accounting_lock;
140 atomic_t outstanding_extents; 139 atomic_t outstanding_extents;
141 int reserved_extents; 140 atomic_t reserved_extents;
142 141
143 /* 142 /*
144 * ordered_data_close is set by truncate when a file that used 143 * ordered_data_close is set by truncate when a file that used
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7b3089b5c2df..27376c97d85f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3996,6 +3996,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
3996 struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; 3996 struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
3997 u64 to_reserve; 3997 u64 to_reserve;
3998 int nr_extents; 3998 int nr_extents;
3999 int reserved_extents;
3999 int ret; 4000 int ret;
4000 4001
4001 if (btrfs_transaction_in_commit(root->fs_info)) 4002 if (btrfs_transaction_in_commit(root->fs_info))
@@ -4003,25 +4004,24 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
4003 4004
4004 num_bytes = ALIGN(num_bytes, root->sectorsize); 4005 num_bytes = ALIGN(num_bytes, root->sectorsize);
4005 4006
4006 spin_lock(&BTRFS_I(inode)->accounting_lock);
4007 nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1; 4007 nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1;
4008 if (nr_extents > BTRFS_I(inode)->reserved_extents) { 4008 reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
4009 nr_extents -= BTRFS_I(inode)->reserved_extents; 4009
4010 if (nr_extents > reserved_extents) {
4011 nr_extents -= reserved_extents;
4010 to_reserve = calc_trans_metadata_size(root, nr_extents); 4012 to_reserve = calc_trans_metadata_size(root, nr_extents);
4011 } else { 4013 } else {
4012 nr_extents = 0; 4014 nr_extents = 0;
4013 to_reserve = 0; 4015 to_reserve = 0;
4014 } 4016 }
4015 spin_unlock(&BTRFS_I(inode)->accounting_lock); 4017
4016 to_reserve += calc_csum_metadata_size(inode, num_bytes); 4018 to_reserve += calc_csum_metadata_size(inode, num_bytes);
4017 ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); 4019 ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1);
4018 if (ret) 4020 if (ret)
4019 return ret; 4021 return ret;
4020 4022
4021 spin_lock(&BTRFS_I(inode)->accounting_lock); 4023 atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents);
4022 BTRFS_I(inode)->reserved_extents += nr_extents;
4023 atomic_inc(&BTRFS_I(inode)->outstanding_extents); 4024 atomic_inc(&BTRFS_I(inode)->outstanding_extents);
4024 spin_unlock(&BTRFS_I(inode)->accounting_lock);
4025 4025
4026 block_rsv_add_bytes(block_rsv, to_reserve, 1); 4026 block_rsv_add_bytes(block_rsv, to_reserve, 1);
4027 4027
@@ -4036,20 +4036,30 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
4036 struct btrfs_root *root = BTRFS_I(inode)->root; 4036 struct btrfs_root *root = BTRFS_I(inode)->root;
4037 u64 to_free; 4037 u64 to_free;
4038 int nr_extents; 4038 int nr_extents;
4039 int reserved_extents;
4039 4040
4040 num_bytes = ALIGN(num_bytes, root->sectorsize); 4041 num_bytes = ALIGN(num_bytes, root->sectorsize);
4041 atomic_dec(&BTRFS_I(inode)->outstanding_extents); 4042 atomic_dec(&BTRFS_I(inode)->outstanding_extents);
4042 WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); 4043 WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0);
4043 4044
4044 spin_lock(&BTRFS_I(inode)->accounting_lock); 4045 reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
4045 nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); 4046 do {
4046 if (nr_extents < BTRFS_I(inode)->reserved_extents) { 4047 int old, new;
4047 nr_extents = BTRFS_I(inode)->reserved_extents - nr_extents; 4048
4048 BTRFS_I(inode)->reserved_extents -= nr_extents; 4049 nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents);
4049 } else { 4050 if (nr_extents >= reserved_extents) {
4050 nr_extents = 0; 4051 nr_extents = 0;
4051 } 4052 break;
4052 spin_unlock(&BTRFS_I(inode)->accounting_lock); 4053 }
4054 old = reserved_extents;
4055 nr_extents = reserved_extents - nr_extents;
4056 new = reserved_extents - nr_extents;
4057 old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents,
4058 reserved_extents, new);
4059 if (likely(old == reserved_extents))
4060 break;
4061 reserved_extents = old;
4062 } while (1);
4053 4063
4054 to_free = calc_csum_metadata_size(inode, num_bytes); 4064 to_free = calc_csum_metadata_size(inode, num_bytes);
4055 if (nr_extents > 0) 4065 if (nr_extents > 0)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 9007bbd01dbf..d97b69afbbfb 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6632,9 +6632,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
6632 ei->index_cnt = (u64)-1; 6632 ei->index_cnt = (u64)-1;
6633 ei->last_unlink_trans = 0; 6633 ei->last_unlink_trans = 0;
6634 6634
6635 spin_lock_init(&ei->accounting_lock);
6636 atomic_set(&ei->outstanding_extents, 0); 6635 atomic_set(&ei->outstanding_extents, 0);
6637 ei->reserved_extents = 0; 6636 atomic_set(&ei->reserved_extents, 0);
6638 6637
6639 ei->ordered_data_close = 0; 6638 ei->ordered_data_close = 0;
6640 ei->orphan_meta_reserved = 0; 6639 ei->orphan_meta_reserved = 0;
@@ -6670,7 +6669,7 @@ void btrfs_destroy_inode(struct inode *inode)
6670 WARN_ON(!list_empty(&inode->i_dentry)); 6669 WARN_ON(!list_empty(&inode->i_dentry));
6671 WARN_ON(inode->i_data.nrpages); 6670 WARN_ON(inode->i_data.nrpages);
6672 WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents)); 6671 WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents));
6673 WARN_ON(BTRFS_I(inode)->reserved_extents); 6672 WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents));
6674 6673
6675 /* 6674 /*
6676 * This can happen where we create an inode, but somebody else also 6675 * This can happen where we create an inode, but somebody else also