diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 18ea90c8943b..0b044e509e9f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4063,23 +4063,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, | |||
4063 | */ | 4063 | */ |
4064 | static unsigned drop_outstanding_extent(struct inode *inode) | 4064 | static unsigned drop_outstanding_extent(struct inode *inode) |
4065 | { | 4065 | { |
4066 | unsigned drop_inode_space = 0; | ||
4066 | unsigned dropped_extents = 0; | 4067 | unsigned dropped_extents = 0; |
4067 | 4068 | ||
4068 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); | 4069 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); |
4069 | BTRFS_I(inode)->outstanding_extents--; | 4070 | BTRFS_I(inode)->outstanding_extents--; |
4070 | 4071 | ||
4072 | if (BTRFS_I(inode)->outstanding_extents == 0 && | ||
4073 | BTRFS_I(inode)->delalloc_meta_reserved) { | ||
4074 | drop_inode_space = 1; | ||
4075 | BTRFS_I(inode)->delalloc_meta_reserved = 0; | ||
4076 | } | ||
4077 | |||
4071 | /* | 4078 | /* |
4072 | * If we have more or the same amount of outsanding extents than we have | 4079 | * If we have more or the same amount of outsanding extents than we have |
4073 | * reserved then we need to leave the reserved extents count alone. | 4080 | * reserved then we need to leave the reserved extents count alone. |
4074 | */ | 4081 | */ |
4075 | if (BTRFS_I(inode)->outstanding_extents >= | 4082 | if (BTRFS_I(inode)->outstanding_extents >= |
4076 | BTRFS_I(inode)->reserved_extents) | 4083 | BTRFS_I(inode)->reserved_extents) |
4077 | return 0; | 4084 | return drop_inode_space; |
4078 | 4085 | ||
4079 | dropped_extents = BTRFS_I(inode)->reserved_extents - | 4086 | dropped_extents = BTRFS_I(inode)->reserved_extents - |
4080 | BTRFS_I(inode)->outstanding_extents; | 4087 | BTRFS_I(inode)->outstanding_extents; |
4081 | BTRFS_I(inode)->reserved_extents -= dropped_extents; | 4088 | BTRFS_I(inode)->reserved_extents -= dropped_extents; |
4082 | return dropped_extents; | 4089 | return dropped_extents + drop_inode_space; |
4083 | } | 4090 | } |
4084 | 4091 | ||
4085 | /** | 4092 | /** |
@@ -4165,9 +4172,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4165 | nr_extents = BTRFS_I(inode)->outstanding_extents - | 4172 | nr_extents = BTRFS_I(inode)->outstanding_extents - |
4166 | BTRFS_I(inode)->reserved_extents; | 4173 | BTRFS_I(inode)->reserved_extents; |
4167 | BTRFS_I(inode)->reserved_extents += nr_extents; | 4174 | BTRFS_I(inode)->reserved_extents += nr_extents; |
4175 | } | ||
4168 | 4176 | ||
4169 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | 4177 | /* |
4178 | * Add an item to reserve for updating the inode when we complete the | ||
4179 | * delalloc io. | ||
4180 | */ | ||
4181 | if (!BTRFS_I(inode)->delalloc_meta_reserved) { | ||
4182 | nr_extents++; | ||
4183 | BTRFS_I(inode)->delalloc_meta_reserved = 1; | ||
4170 | } | 4184 | } |
4185 | |||
4186 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | ||
4171 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); | 4187 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); |
4172 | spin_unlock(&BTRFS_I(inode)->lock); | 4188 | spin_unlock(&BTRFS_I(inode)->lock); |
4173 | 4189 | ||