summaryrefslogtreecommitdiff
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-07-15 15:16:44 +0000
committerChris Mason <chris.mason@oracle.com>2011-07-27 12:46:44 -0400
commit9e0baf60dea69f31ac3b1adeb35b03b02a53e8e1 (patch)
tree0fb899e1fa78b599d22389ca3befc8ab51ff5049 /fs/btrfs/ioctl.c
parenta5991428064e98c7367fe1c1686ea6a23fb6a4b3 (diff)
downloadlinux-3.10-9e0baf60dea69f31ac3b1adeb35b03b02a53e8e1.tar.gz
linux-3.10-9e0baf60dea69f31ac3b1adeb35b03b02a53e8e1.tar.bz2
linux-3.10-9e0baf60dea69f31ac3b1adeb35b03b02a53e8e1.zip
Btrfs: fix enospc problems with delalloc
So I had this brilliant idea to use atomic counters for outstanding and reserved extents, but this turned out to be a bad idea. Consider this where we have 1 outstanding extent and 1 reserved extent Reserver Releaser atomic_dec(outstanding) now 0 atomic_read(outstanding)+1 get 1 atomic_read(reserved) get 1 don't actually reserve anything because they are the same atomic_cmpxchg(reserved, 1, 0) atomic_inc(outstanding) atomic_add(0, reserved) free reserved space for 1 extent Then the reserver now has no actual space reserved for it, and when it goes to finish the ordered IO it won't have enough space to do it's allocation and you get those lovely warnings. Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 09c9a8d26ee..fd252fff4c6 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -938,7 +938,9 @@ again:
GFP_NOFS);
if (i_done != num_pages) {
- atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+ spin_lock(&BTRFS_I(inode)->lock);
+ BTRFS_I(inode)->outstanding_extents++;
+ spin_unlock(&BTRFS_I(inode)->lock);
btrfs_delalloc_release_space(inode,
(num_pages - i_done) << PAGE_CACHE_SHIFT);
}