aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-07-15 11:16:44 -0400
committerChris Mason <chris.mason@oracle.com>2011-07-27 12:46:44 -0400
commit9e0baf60dea69f31ac3b1adeb35b03b02a53e8e1 (patch)
tree0fb899e1fa78b599d22389ca3befc8ab51ff5049 /fs/btrfs/inode.c
parenta5991428064e98c7367fe1c1686ea6a23fb6a4b3 (diff)
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/inode.c')
-rw-r--r--fs/btrfs/inode.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2bf4d2b97d54..55d68ea1866b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1298,7 +1298,9 @@ static int btrfs_split_extent_hook(struct inode *inode,
1298 if (!(orig->state & EXTENT_DELALLOC)) 1298 if (!(orig->state & EXTENT_DELALLOC))
1299 return 0; 1299 return 0;
1300 1300
1301 atomic_inc(&BTRFS_I(inode)->outstanding_extents); 1301 spin_lock(&BTRFS_I(inode)->lock);
1302 BTRFS_I(inode)->outstanding_extents++;
1303 spin_unlock(&BTRFS_I(inode)->lock);
1302 return 0; 1304 return 0;
1303} 1305}
1304 1306
@@ -1316,7 +1318,9 @@ static int btrfs_merge_extent_hook(struct inode *inode,
1316 if (!(other->state & EXTENT_DELALLOC)) 1318 if (!(other->state & EXTENT_DELALLOC))
1317 return 0; 1319 return 0;
1318 1320
1319 atomic_dec(&BTRFS_I(inode)->outstanding_extents); 1321 spin_lock(&BTRFS_I(inode)->lock);
1322 BTRFS_I(inode)->outstanding_extents--;
1323 spin_unlock(&BTRFS_I(inode)->lock);
1320 return 0; 1324 return 0;
1321} 1325}
1322 1326
@@ -1339,10 +1343,13 @@ static int btrfs_set_bit_hook(struct inode *inode,
1339 u64 len = state->end + 1 - state->start; 1343 u64 len = state->end + 1 - state->start;
1340 bool do_list = !is_free_space_inode(root, inode); 1344 bool do_list = !is_free_space_inode(root, inode);
1341 1345
1342 if (*bits & EXTENT_FIRST_DELALLOC) 1346 if (*bits & EXTENT_FIRST_DELALLOC) {
1343 *bits &= ~EXTENT_FIRST_DELALLOC; 1347 *bits &= ~EXTENT_FIRST_DELALLOC;
1344 else 1348 } else {
1345 atomic_inc(&BTRFS_I(inode)->outstanding_extents); 1349 spin_lock(&BTRFS_I(inode)->lock);
1350 BTRFS_I(inode)->outstanding_extents++;
1351 spin_unlock(&BTRFS_I(inode)->lock);
1352 }
1346 1353
1347 spin_lock(&root->fs_info->delalloc_lock); 1354 spin_lock(&root->fs_info->delalloc_lock);
1348 BTRFS_I(inode)->delalloc_bytes += len; 1355 BTRFS_I(inode)->delalloc_bytes += len;
@@ -1372,10 +1379,13 @@ static int btrfs_clear_bit_hook(struct inode *inode,
1372 u64 len = state->end + 1 - state->start; 1379 u64 len = state->end + 1 - state->start;
1373 bool do_list = !is_free_space_inode(root, inode); 1380 bool do_list = !is_free_space_inode(root, inode);
1374 1381
1375 if (*bits & EXTENT_FIRST_DELALLOC) 1382 if (*bits & EXTENT_FIRST_DELALLOC) {
1376 *bits &= ~EXTENT_FIRST_DELALLOC; 1383 *bits &= ~EXTENT_FIRST_DELALLOC;
1377 else if (!(*bits & EXTENT_DO_ACCOUNTING)) 1384 } else if (!(*bits & EXTENT_DO_ACCOUNTING)) {
1378 atomic_dec(&BTRFS_I(inode)->outstanding_extents); 1385 spin_lock(&BTRFS_I(inode)->lock);
1386 BTRFS_I(inode)->outstanding_extents--;
1387 spin_unlock(&BTRFS_I(inode)->lock);
1388 }
1379 1389
1380 if (*bits & EXTENT_DO_ACCOUNTING) 1390 if (*bits & EXTENT_DO_ACCOUNTING)
1381 btrfs_delalloc_release_metadata(inode, len); 1391 btrfs_delalloc_release_metadata(inode, len);
@@ -6735,8 +6745,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
6735 ei->index_cnt = (u64)-1; 6745 ei->index_cnt = (u64)-1;
6736 ei->last_unlink_trans = 0; 6746 ei->last_unlink_trans = 0;
6737 6747
6738 atomic_set(&ei->outstanding_extents, 0); 6748 spin_lock_init(&ei->lock);
6739 atomic_set(&ei->reserved_extents, 0); 6749 ei->outstanding_extents = 0;
6750 ei->reserved_extents = 0;
6740 6751
6741 ei->ordered_data_close = 0; 6752 ei->ordered_data_close = 0;
6742 ei->orphan_meta_reserved = 0; 6753 ei->orphan_meta_reserved = 0;
@@ -6774,8 +6785,8 @@ void btrfs_destroy_inode(struct inode *inode)
6774 6785
6775 WARN_ON(!list_empty(&inode->i_dentry)); 6786 WARN_ON(!list_empty(&inode->i_dentry));
6776 WARN_ON(inode->i_data.nrpages); 6787 WARN_ON(inode->i_data.nrpages);
6777 WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents)); 6788 WARN_ON(BTRFS_I(inode)->outstanding_extents);
6778 WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents)); 6789 WARN_ON(BTRFS_I(inode)->reserved_extents);
6779 6790
6780 /* 6791 /*
6781 * This can happen where we create an inode, but somebody else also 6792 * This can happen where we create an inode, but somebody else also