Message ID | orvc9lqsgt.fsf@livre.home (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Feb 21, 2013 at 02:15:14PM -0700, Alexandre Oliva wrote: > I've experienced filesystem freezes with permanent spikes in the active > process count for quite a while, particularly on filesystems whose > available raw space has already been fully allocated to chunks. > > While looking into this, I found a pretty obvious error in > do_chunk_alloc: it sets space_info->chunk_alloc, but if > btrfs_alloc_chunk returns an error other than ENOSPC, it returns leaving > that flag set, which causes any other threads waiting for > space_info->chunk_alloc to become zero to spin indefinitely. > > I haven't double-checked that this patch fixes the failure I've observed > fully (it's not exactly trivial to trigger), but it surely is a bug and > the fix is trivial, so... Please put it in :-) Yup putting in btrfs-next, thanks. Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
btrfs: clear chunk_alloc flag on retryable failure From: Alexandre Oliva <oliva@gnu.org> If btrfs_alloc_chunk fails with e.g. ENOMEM, we exit do_chunk_alloc without clearing chunk_alloc in space_info. As a result, any further calls to do_chunk_alloc on that filesystem will start busy-waiting for chunk_alloc to be cleared, but it never will be. This patch adjusts do_chunk_alloc so that it clears this flag in case of an error. Signed-off-by: Alexandre Oliva <oliva@gnu.org> --- fs/btrfs/extent-tree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5a3327b..b597cdf 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3632,19 +3632,21 @@ again: check_system_chunk(trans, extent_root, flags); ret = btrfs_alloc_chunk(trans, extent_root, flags); + + spin_lock(&space_info->lock); + if (ret < 0 && ret != -ENOSPC) goto out; - spin_lock(&space_info->lock); if (ret) space_info->full = 1; else ret = 1; space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; +out: space_info->chunk_alloc = 0; spin_unlock(&space_info->lock); -out: mutex_unlock(&fs_info->chunk_mutex); return ret; }