* [PATCH 1/3] Btrfs: fix check_path_shared so it returns the right value
2011-01-24 21:43 ENOSPC fixes Josef Bacik
@ 2011-01-24 21:43 ` Josef Bacik
2011-01-24 21:43 ` [PATCH 2/3] Btrfs: do not release more reserved bytes to the global_block_rsv than we need Josef Bacik
2011-01-24 21:43 ` [PATCH 3/3] Btrfs: use the global block reserve if we cannot reserve space Josef Bacik
2 siblings, 0 replies; 4+ messages in thread
From: Josef Bacik @ 2011-01-24 21:43 UTC (permalink / raw)
To: linux-btrfs
When running xfstests 224 I kept getting ENOSPC when trying to remove the files,
and this is because we were returning ret from check_path_shared while it was
uninitalized, which isn't right. Fix this to return 0 properly, and now
xfstests 224 doesn't freak out when it tries to clean itself up. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
---
fs/btrfs/inode.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 160b55b..e353da5 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2714,9 +2714,10 @@ static int check_path_shared(struct btrfs_root *root,
struct extent_buffer *eb;
int level;
u64 refs = 1;
- int uninitialized_var(ret);
for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
+ int ret;
+
if (!path->nodes[level])
break;
eb = path->nodes[level];
@@ -2727,7 +2728,7 @@ static int check_path_shared(struct btrfs_root *root,
if (refs > 1)
return 1;
}
- return ret; /* XXX callers? */
+ return 0;
}
/*
--
1.6.6.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] Btrfs: do not release more reserved bytes to the global_block_rsv than we need
2011-01-24 21:43 ENOSPC fixes Josef Bacik
2011-01-24 21:43 ` [PATCH 1/3] Btrfs: fix check_path_shared so it returns the right value Josef Bacik
@ 2011-01-24 21:43 ` Josef Bacik
2011-01-24 21:43 ` [PATCH 3/3] Btrfs: use the global block reserve if we cannot reserve space Josef Bacik
2 siblings, 0 replies; 4+ messages in thread
From: Josef Bacik @ 2011-01-24 21:43 UTC (permalink / raw)
To: linux-btrfs
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>
---
fs/btrfs/extent-tree.c | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7ad7bf2..7aed7bf 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3599,8 +3599,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);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] Btrfs: use the global block reserve if we cannot reserve space
2011-01-24 21:43 ENOSPC fixes Josef Bacik
2011-01-24 21:43 ` [PATCH 1/3] Btrfs: fix check_path_shared so it returns the right value Josef Bacik
2011-01-24 21:43 ` [PATCH 2/3] Btrfs: do not release more reserved bytes to the global_block_rsv than we need Josef Bacik
@ 2011-01-24 21:43 ` Josef Bacik
2 siblings, 0 replies; 4+ messages in thread
From: Josef Bacik @ 2011-01-24 21:43 UTC (permalink / raw)
To: linux-btrfs
We call use_block_rsv right before we make an allocation in order to make sure
we have enough space. Now normally people have called btrfs_start_transaction()
with the appropriate amount of space that we need, so we just use some of that
pre-reserved space and move along happily. The problem is where people use
btrfs_join_transaction(), which doesn't actually reserve any space. So we try
and reserve space here, but we cannot flush delalloc, so this forces us to
return -ENOSPC when in reality we have plenty of space. The most common symptom
is seeing a bunch of "couldn't dirty inode" messages in syslog. With
xfstests 224 we end up falling back to start_transaction and then doing all the
flush delalloc stuff which causes to hang for a very long time.
So instead steal from the global reserve, which is what this is meant for
anyway. With this patch and the other 2 I have sent xfstests 224 now passes
successfully. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
---
fs/btrfs/extent-tree.c | 28 +++++++++++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7aed7bf..355665b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5656,6 +5656,7 @@ use_block_rsv(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u32 blocksize)
{
struct btrfs_block_rsv *block_rsv;
+ struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
int ret;
block_rsv = get_block_rsv(trans, root);
@@ -5663,14 +5664,39 @@ use_block_rsv(struct btrfs_trans_handle *trans,
if (block_rsv->size == 0) {
ret = reserve_metadata_bytes(trans, root, block_rsv,
blocksize, 0);
- if (ret)
+ /*
+ * If we couldn't reserve metadata bytes try and use some from
+ * the global reserve.
+ */
+ if (ret && block_rsv != global_rsv) {
+ ret = block_rsv_use_bytes(global_rsv, blocksize);
+ if (!ret)
+ return global_rsv;
+ return ERR_PTR(ret);
+ } else if (ret) {
return ERR_PTR(ret);
+ }
return block_rsv;
}
ret = block_rsv_use_bytes(block_rsv, blocksize);
if (!ret)
return block_rsv;
+ if (ret) {
+ WARN_ON(1);
+ ret = reserve_metadata_bytes(trans, root, block_rsv, blocksize,
+ 0);
+ if (!ret) {
+ spin_lock(&block_rsv->lock);
+ block_rsv->size += blocksize;
+ spin_unlock(&block_rsv->lock);
+ return block_rsv;
+ } else if (ret && block_rsv != global_rsv) {
+ ret = block_rsv_use_bytes(global_rsv, blocksize);
+ if (!ret)
+ return global_rsv;
+ }
+ }
return ERR_PTR(-ENOSPC);
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 4+ messages in thread