diff options
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 6 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 117 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 3 |
3 files changed, 118 insertions, 8 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index c70fb10a307b..5a5d325a3935 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -123,6 +123,12 @@ struct btrfs_inode { | |||
123 | */ | 123 | */ |
124 | u64 last_unlink_trans; | 124 | u64 last_unlink_trans; |
125 | 125 | ||
126 | /* | ||
127 | * Number of bytes outstanding that are going to need csums. This is | ||
128 | * used in ENOSPC accounting. | ||
129 | */ | ||
130 | u64 csum_bytes; | ||
131 | |||
126 | /* flags field from the on disk inode */ | 132 | /* flags field from the on disk inode */ |
127 | u32 flags; | 133 | u32 flags; |
128 | 134 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fbe6278f466b..4add1ac2dda0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3984,11 +3984,19 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, | |||
3984 | return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); | 3984 | return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); |
3985 | } | 3985 | } |
3986 | 3986 | ||
3987 | /** | ||
3988 | * drop_outstanding_extent - drop an outstanding extent | ||
3989 | * @inode: the inode we're dropping the extent for | ||
3990 | * | ||
3991 | * This is called when we are freeing up an outstanding extent, either called | ||
3992 | * after an error or after an extent is written. This will return the number of | ||
3993 | * reserved extents that need to be freed. This must be called with | ||
3994 | * BTRFS_I(inode)->lock held. | ||
3995 | */ | ||
3987 | static unsigned drop_outstanding_extent(struct inode *inode) | 3996 | static unsigned drop_outstanding_extent(struct inode *inode) |
3988 | { | 3997 | { |
3989 | unsigned dropped_extents = 0; | 3998 | unsigned dropped_extents = 0; |
3990 | 3999 | ||
3991 | spin_lock(&BTRFS_I(inode)->lock); | ||
3992 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); | 4000 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); |
3993 | BTRFS_I(inode)->outstanding_extents--; | 4001 | BTRFS_I(inode)->outstanding_extents--; |
3994 | 4002 | ||
@@ -3998,19 +4006,70 @@ static unsigned drop_outstanding_extent(struct inode *inode) | |||
3998 | */ | 4006 | */ |
3999 | if (BTRFS_I(inode)->outstanding_extents >= | 4007 | if (BTRFS_I(inode)->outstanding_extents >= |
4000 | BTRFS_I(inode)->reserved_extents) | 4008 | BTRFS_I(inode)->reserved_extents) |
4001 | goto out; | 4009 | return 0; |
4002 | 4010 | ||
4003 | dropped_extents = BTRFS_I(inode)->reserved_extents - | 4011 | dropped_extents = BTRFS_I(inode)->reserved_extents - |
4004 | BTRFS_I(inode)->outstanding_extents; | 4012 | BTRFS_I(inode)->outstanding_extents; |
4005 | BTRFS_I(inode)->reserved_extents -= dropped_extents; | 4013 | BTRFS_I(inode)->reserved_extents -= dropped_extents; |
4006 | out: | ||
4007 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4008 | return dropped_extents; | 4014 | return dropped_extents; |
4009 | } | 4015 | } |
4010 | 4016 | ||
4011 | static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes) | 4017 | /** |
4018 | * calc_csum_metadata_size - return the amount of metada space that must be | ||
4019 | * reserved/free'd for the given bytes. | ||
4020 | * @inode: the inode we're manipulating | ||
4021 | * @num_bytes: the number of bytes in question | ||
4022 | * @reserve: 1 if we are reserving space, 0 if we are freeing space | ||
4023 | * | ||
4024 | * This adjusts the number of csum_bytes in the inode and then returns the | ||
4025 | * correct amount of metadata that must either be reserved or freed. We | ||
4026 | * calculate how many checksums we can fit into one leaf and then divide the | ||
4027 | * number of bytes that will need to be checksumed by this value to figure out | ||
4028 | * how many checksums will be required. If we are adding bytes then the number | ||
4029 | * may go up and we will return the number of additional bytes that must be | ||
4030 | * reserved. If it is going down we will return the number of bytes that must | ||
4031 | * be freed. | ||
4032 | * | ||
4033 | * This must be called with BTRFS_I(inode)->lock held. | ||
4034 | */ | ||
4035 | static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes, | ||
4036 | int reserve) | ||
4012 | { | 4037 | { |
4013 | return num_bytes >>= 3; | 4038 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4039 | u64 csum_size; | ||
4040 | int num_csums_per_leaf; | ||
4041 | int num_csums; | ||
4042 | int old_csums; | ||
4043 | |||
4044 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM && | ||
4045 | BTRFS_I(inode)->csum_bytes == 0) | ||
4046 | return 0; | ||
4047 | |||
4048 | old_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize); | ||
4049 | if (reserve) | ||
4050 | BTRFS_I(inode)->csum_bytes += num_bytes; | ||
4051 | else | ||
4052 | BTRFS_I(inode)->csum_bytes -= num_bytes; | ||
4053 | csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item); | ||
4054 | num_csums_per_leaf = (int)div64_u64(csum_size, | ||
4055 | sizeof(struct btrfs_csum_item) + | ||
4056 | sizeof(struct btrfs_disk_key)); | ||
4057 | num_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize); | ||
4058 | num_csums = num_csums + num_csums_per_leaf - 1; | ||
4059 | num_csums = num_csums / num_csums_per_leaf; | ||
4060 | |||
4061 | old_csums = old_csums + num_csums_per_leaf - 1; | ||
4062 | old_csums = old_csums / num_csums_per_leaf; | ||
4063 | |||
4064 | /* No change, no need to reserve more */ | ||
4065 | if (old_csums == num_csums) | ||
4066 | return 0; | ||
4067 | |||
4068 | if (reserve) | ||
4069 | return btrfs_calc_trans_metadata_size(root, | ||
4070 | num_csums - old_csums); | ||
4071 | |||
4072 | return btrfs_calc_trans_metadata_size(root, old_csums - num_csums); | ||
4014 | } | 4073 | } |
4015 | 4074 | ||
4016 | int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | 4075 | int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) |
@@ -4037,9 +4096,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4037 | 4096 | ||
4038 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | 4097 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); |
4039 | } | 4098 | } |
4099 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); | ||
4040 | spin_unlock(&BTRFS_I(inode)->lock); | 4100 | spin_unlock(&BTRFS_I(inode)->lock); |
4041 | 4101 | ||
4042 | to_reserve += calc_csum_metadata_size(inode, num_bytes); | ||
4043 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); | 4102 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); |
4044 | if (ret) { | 4103 | if (ret) { |
4045 | unsigned dropped; | 4104 | unsigned dropped; |
@@ -4047,8 +4106,11 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4047 | * We don't need the return value since our reservation failed, | 4106 | * We don't need the return value since our reservation failed, |
4048 | * we just need to clean up our counter. | 4107 | * we just need to clean up our counter. |
4049 | */ | 4108 | */ |
4109 | spin_lock(&BTRFS_I(inode)->lock); | ||
4050 | dropped = drop_outstanding_extent(inode); | 4110 | dropped = drop_outstanding_extent(inode); |
4051 | WARN_ON(dropped > 1); | 4111 | WARN_ON(dropped > 1); |
4112 | BTRFS_I(inode)->csum_bytes -= num_bytes; | ||
4113 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4052 | return ret; | 4114 | return ret; |
4053 | } | 4115 | } |
4054 | 4116 | ||
@@ -4057,6 +4119,15 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4057 | return 0; | 4119 | return 0; |
4058 | } | 4120 | } |
4059 | 4121 | ||
4122 | /** | ||
4123 | * btrfs_delalloc_release_metadata - release a metadata reservation for an inode | ||
4124 | * @inode: the inode to release the reservation for | ||
4125 | * @num_bytes: the number of bytes we're releasing | ||
4126 | * | ||
4127 | * This will release the metadata reservation for an inode. This can be called | ||
4128 | * once we complete IO for a given set of bytes to release their metadata | ||
4129 | * reservations. | ||
4130 | */ | ||
4060 | void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | 4131 | void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) |
4061 | { | 4132 | { |
4062 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4133 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -4064,9 +4135,11 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
4064 | unsigned dropped; | 4135 | unsigned dropped; |
4065 | 4136 | ||
4066 | num_bytes = ALIGN(num_bytes, root->sectorsize); | 4137 | num_bytes = ALIGN(num_bytes, root->sectorsize); |
4138 | spin_lock(&BTRFS_I(inode)->lock); | ||
4067 | dropped = drop_outstanding_extent(inode); | 4139 | dropped = drop_outstanding_extent(inode); |
4068 | 4140 | ||
4069 | to_free = calc_csum_metadata_size(inode, num_bytes); | 4141 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); |
4142 | spin_unlock(&BTRFS_I(inode)->lock); | ||
4070 | if (dropped > 0) | 4143 | if (dropped > 0) |
4071 | to_free += btrfs_calc_trans_metadata_size(root, dropped); | 4144 | to_free += btrfs_calc_trans_metadata_size(root, dropped); |
4072 | 4145 | ||
@@ -4074,6 +4147,21 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
4074 | to_free); | 4147 | to_free); |
4075 | } | 4148 | } |
4076 | 4149 | ||
4150 | /** | ||
4151 | * btrfs_delalloc_reserve_space - reserve data and metadata space for delalloc | ||
4152 | * @inode: inode we're writing to | ||
4153 | * @num_bytes: the number of bytes we want to allocate | ||
4154 | * | ||
4155 | * This will do the following things | ||
4156 | * | ||
4157 | * o reserve space in the data space info for num_bytes | ||
4158 | * o reserve space in the metadata space info based on number of outstanding | ||
4159 | * extents and how much csums will be needed | ||
4160 | * o add to the inodes ->delalloc_bytes | ||
4161 | * o add it to the fs_info's delalloc inodes list. | ||
4162 | * | ||
4163 | * This will return 0 for success and -ENOSPC if there is no space left. | ||
4164 | */ | ||
4077 | int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes) | 4165 | int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes) |
4078 | { | 4166 | { |
4079 | int ret; | 4167 | int ret; |
@@ -4091,6 +4179,19 @@ int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes) | |||
4091 | return 0; | 4179 | return 0; |
4092 | } | 4180 | } |
4093 | 4181 | ||
4182 | /** | ||
4183 | * btrfs_delalloc_release_space - release data and metadata space for delalloc | ||
4184 | * @inode: inode we're releasing space for | ||
4185 | * @num_bytes: the number of bytes we want to free up | ||
4186 | * | ||
4187 | * This must be matched with a call to btrfs_delalloc_reserve_space. This is | ||
4188 | * called in the case that we don't need the metadata AND data reservations | ||
4189 | * anymore. So if there is an error or we insert an inline extent. | ||
4190 | * | ||
4191 | * This function will release the metadata space that was not used and will | ||
4192 | * decrement ->delalloc_bytes and remove it from the fs_info delalloc_inodes | ||
4193 | * list if there are no delalloc bytes left. | ||
4194 | */ | ||
4094 | void btrfs_delalloc_release_space(struct inode *inode, u64 num_bytes) | 4195 | void btrfs_delalloc_release_space(struct inode *inode, u64 num_bytes) |
4095 | { | 4196 | { |
4096 | btrfs_delalloc_release_metadata(inode, num_bytes); | 4197 | btrfs_delalloc_release_metadata(inode, num_bytes); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 156c3a0da792..98b9fa2d77f7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6757,6 +6757,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
6757 | ei->delalloc_bytes = 0; | 6757 | ei->delalloc_bytes = 0; |
6758 | ei->disk_i_size = 0; | 6758 | ei->disk_i_size = 0; |
6759 | ei->flags = 0; | 6759 | ei->flags = 0; |
6760 | ei->csum_bytes = 0; | ||
6760 | ei->index_cnt = (u64)-1; | 6761 | ei->index_cnt = (u64)-1; |
6761 | ei->last_unlink_trans = 0; | 6762 | ei->last_unlink_trans = 0; |
6762 | 6763 | ||
@@ -6802,6 +6803,8 @@ void btrfs_destroy_inode(struct inode *inode) | |||
6802 | WARN_ON(inode->i_data.nrpages); | 6803 | WARN_ON(inode->i_data.nrpages); |
6803 | WARN_ON(BTRFS_I(inode)->outstanding_extents); | 6804 | WARN_ON(BTRFS_I(inode)->outstanding_extents); |
6804 | WARN_ON(BTRFS_I(inode)->reserved_extents); | 6805 | WARN_ON(BTRFS_I(inode)->reserved_extents); |
6806 | WARN_ON(BTRFS_I(inode)->delalloc_bytes); | ||
6807 | WARN_ON(BTRFS_I(inode)->csum_bytes); | ||
6805 | 6808 | ||
6806 | /* | 6809 | /* |
6807 | * This can happen where we create an inode, but somebody else also | 6810 | * This can happen where we create an inode, but somebody else also |