aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent-tree.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a8ff25aedca1..a22b5cc921ad 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4815,14 +4815,49 @@ out_fail:
4815 * If the inodes csum_bytes is the same as the original 4815 * If the inodes csum_bytes is the same as the original
4816 * csum_bytes then we know we haven't raced with any free()ers 4816 * csum_bytes then we know we haven't raced with any free()ers
4817 * so we can just reduce our inodes csum bytes and carry on. 4817 * so we can just reduce our inodes csum bytes and carry on.
4818 * Otherwise we have to do the normal free thing to account for
4819 * the case that the free side didn't free up its reserve
4820 * because of this outstanding reservation.
4821 */ 4818 */
4822 if (BTRFS_I(inode)->csum_bytes == csum_bytes) 4819 if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
4823 calc_csum_metadata_size(inode, num_bytes, 0); 4820 calc_csum_metadata_size(inode, num_bytes, 0);
4824 else 4821 } else {
4825 to_free = calc_csum_metadata_size(inode, num_bytes, 0); 4822 u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
4823 u64 bytes;
4824
4825 /*
4826 * This is tricky, but first we need to figure out how much we
4827 * free'd from any free-ers that occured during this
4828 * reservation, so we reset ->csum_bytes to the csum_bytes
4829 * before we dropped our lock, and then call the free for the
4830 * number of bytes that were freed while we were trying our
4831 * reservation.
4832 */
4833 bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
4834 BTRFS_I(inode)->csum_bytes = csum_bytes;
4835 to_free = calc_csum_metadata_size(inode, bytes, 0);
4836
4837
4838 /*
4839 * Now we need to see how much we would have freed had we not
4840 * been making this reservation and our ->csum_bytes were not
4841 * artificially inflated.
4842 */
4843 BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
4844 bytes = csum_bytes - orig_csum_bytes;
4845 bytes = calc_csum_metadata_size(inode, bytes, 0);
4846
4847 /*
4848 * Now reset ->csum_bytes to what it should be. If bytes is
4849 * more than to_free then we would have free'd more space had we
4850 * not had an artificially high ->csum_bytes, so we need to free
4851 * the remainder. If bytes is the same or less then we don't
4852 * need to do anything, the other free-ers did the correct
4853 * thing.
4854 */
4855 BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
4856 if (bytes > to_free)
4857 to_free = bytes - to_free;
4858 else
4859 to_free = 0;
4860 }
4826 spin_unlock(&BTRFS_I(inode)->lock); 4861 spin_unlock(&BTRFS_I(inode)->lock);
4827 if (dropped) 4862 if (dropped)
4828 to_free += btrfs_calc_trans_metadata_size(root, dropped); 4863 to_free += btrfs_calc_trans_metadata_size(root, dropped);