On 08/01/17 03:06, gregkh@xxxxxxxxxxxxxxxxxxx wrote: > > The patch below does not apply to the 4.9-stable tree. > If someone wants it applied there, or to any other stable or longterm > tree, then please email the backport, including the original git commit > id to <stable@xxxxxxxxxxxxxxx>. > > thanks, > > greg k-h > > ------------------ original commit in Linus's tree ------------------ > > From 17024ad0a0fdfcfe53043afb969b813d3e020c21 Mon Sep 17 00:00:00 2001 > From: Omar Sandoval <osandov@xxxxxx> > Date: Thu, 20 Jul 2017 15:10:35 -0700 > Subject: [PATCH] Btrfs: fix early ENOSPC due to delalloc > > If a lot of metadata is reserved for outstanding delayed allocations, we > rely on shrink_delalloc() to reclaim metadata space in order to fulfill > reservation tickets. However, shrink_delalloc() has a shortcut where if > it determines that space can be overcommitted, it will stop early. This > made sense before the ticketed enospc system, but now it means that > shrink_delalloc() will often not reclaim enough space to fulfill any > tickets, leading to an early ENOSPC. (Reservation tickets don't care > about being able to overcommit, they need every byte accounted for.) > > Fix it by getting rid of the shortcut so that shrink_delalloc() reclaims > all of the metadata it is supposed to. This fixes early ENOSPCs we were > seeing when doing a btrfs receive to populate a new filesystem, as well > as early ENOSPCs Christoph saw when doing a big cp -r onto Btrfs. > > Fixes: 957780eb2788 ("Btrfs: introduce ticketed enospc infrastructure") > Tested-by: Christoph Anton Mitterer <mail@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx > Reviewed-by: Josef Bacik <jbacik@xxxxxx> > Signed-off-by: Omar Sandoval <osandov@xxxxxx> > Signed-off-by: David Sterba <dsterba@xxxxxxxx> > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > index a6635f07b8f1..e3b0b4196d3d 100644 > --- a/fs/btrfs/extent-tree.c > +++ b/fs/btrfs/extent-tree.c > @@ -4825,10 +4825,6 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info, u64 to_reclaim, > else > flush = BTRFS_RESERVE_NO_FLUSH; > spin_lock(&space_info->lock); > - if (can_overcommit(fs_info, space_info, orig, flush, false)) { > - spin_unlock(&space_info->lock); > - break; > - } > if (list_empty(&space_info->tickets) && > list_empty(&space_info->priority_tickets)) { > spin_unlock(&space_info->lock); > This is kind of important to have, so attached is the backport for 4.9.40 that I've been using; I just rediffed it to apply cleanly. For 4.12.x someone else needs to step up. -h Signed-off-by: Holger Hoffstätte <holger@xxxxxxxxxxxxxxxxxxxxxx> diff -rup linux-4.9.40/fs/btrfs/extent-tree.c linux-4.9.40+/fs/btrfs/extent-tree.c --- linux-4.9.40/fs/btrfs/extent-tree.c 2017-06-29 13:00:49.000000000 +0200 +++ linux-4.9.40+/fs/btrfs/extent-tree.c 2017-08-04 19:05:27.717936241 +0200 @@ -4759,10 +4759,6 @@ skip_async: else flush = BTRFS_RESERVE_NO_FLUSH; spin_lock(&space_info->lock); - if (can_overcommit(root, space_info, orig, flush)) { - spin_unlock(&space_info->lock); - break; - } if (list_empty(&space_info->tickets) && list_empty(&space_info->priority_tickets)) { spin_unlock(&space_info->lock);