Btrfs: do not release more reserved bytes to the global_block_rsv than we need
authorJosef Bacik <josef@redhat.com>
Mon, 24 Jan 2011 21:43:19 +0000 (21:43 +0000)
committerChris Mason <chris.mason@oracle.com>
Fri, 28 Jan 2011 21:40:37 +0000 (16:40 -0500)
When we do btrfs_block_rsv_release, if global_block_rsv is not full we will
release all the extra bytes to global_block_rsv, even if it's only a little
short of the amount of space that we need to reserve.  This causes us to starve
ourselves of reservable space during the transaction which will force us to
shrink delalloc bytes and commit the transaction more often than we should.  So
instead just add the amount of bytes we need to add to the global reserve so
reserved == size, and then add the rest back into the space_info for general
use.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/extent-tree.c

index 98ee139885ccb1ba33b4598dcf0e77aec58f46f1..7af618dcf2c09f0e7a217e850ad1c84fdd4a7b22 100644 (file)
@@ -3589,8 +3589,20 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv,
 
        if (num_bytes > 0) {
                if (dest) {
-                       block_rsv_add_bytes(dest, num_bytes, 0);
-               } else {
+                       spin_lock(&dest->lock);
+                       if (!dest->full) {
+                               u64 bytes_to_add;
+
+                               bytes_to_add = dest->size - dest->reserved;
+                               bytes_to_add = min(num_bytes, bytes_to_add);
+                               dest->reserved += bytes_to_add;
+                               if (dest->reserved >= dest->size)
+                                       dest->full = 1;
+                               num_bytes -= bytes_to_add;
+                       }
+                       spin_unlock(&dest->lock);
+               }
+               if (num_bytes) {
                        spin_lock(&space_info->lock);
                        space_info->bytes_reserved -= num_bytes;
                        spin_unlock(&space_info->lock);