stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Maxim Patlasov <mpatlasov@virtuozzo.com>,
	Chris Mason <clm@fb.com>
Subject: [PATCH 4.4 01/60] btrfs: limit async_work allocation and worker func duration
Date: Wed,  4 Jan 2017 21:46:46 +0100	[thread overview]
Message-ID: <20170104200705.689931149@linuxfoundation.org> (raw)
In-Reply-To: <20170104200705.627445996@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Maxim Patlasov <mpatlasov@virtuozzo.com>

commit 2939e1a86f758b55cdba73e29397dd3d94df13bc upstream.

Problem statement: unprivileged user who has read-write access to more than
one btrfs subvolume may easily consume all kernel memory (eventually
triggering oom-killer).

Reproducer (./mkrmdir below essentially loops over mkdir/rmdir):

[root@kteam1 ~]# cat prep.sh

DEV=/dev/sdb
mkfs.btrfs -f $DEV
mount $DEV /mnt
for i in `seq 1 16`
do
	mkdir /mnt/$i
	btrfs subvolume create /mnt/SV_$i
	ID=`btrfs subvolume list /mnt |grep "SV_$i$" |cut -d ' ' -f 2`
	mount -t btrfs -o subvolid=$ID $DEV /mnt/$i
	chmod a+rwx /mnt/$i
done

[root@kteam1 ~]# sh prep.sh

[maxim@kteam1 ~]$ for i in `seq 1 16`; do ./mkrmdir /mnt/$i 2000 2000 & done

[root@kteam1 ~]# for i in `seq 1 4`; do grep "kmalloc-128" /proc/slabinfo | grep -v dma; sleep 60; done
kmalloc-128        10144  10144    128   32    1 : tunables    0    0    0 : slabdata    317    317      0
kmalloc-128       9992352 9992352    128   32    1 : tunables    0    0    0 : slabdata 312261 312261      0
kmalloc-128       24226752 24226752    128   32    1 : tunables    0    0    0 : slabdata 757086 757086      0
kmalloc-128       42754240 42754240    128   32    1 : tunables    0    0    0 : slabdata 1336070 1336070      0

The huge numbers above come from insane number of async_work-s allocated
and queued by btrfs_wq_run_delayed_node.

The problem is caused by btrfs_wq_run_delayed_node() queuing more and more
works if the number of delayed items is above BTRFS_DELAYED_BACKGROUND. The
worker func (btrfs_async_run_delayed_root) processes at least
BTRFS_DELAYED_BATCH items (if they are present in the list). So, the machinery
works as expected while the list is almost empty. As soon as it is getting
bigger, worker func starts to process more than one item at a time, it takes
longer, and the chances to have async_works queued more than needed is getting
higher.

The problem above is worsened by another flaw of delayed-inode implementation:
if async_work was queued in a throttling branch (number of items >=
BTRFS_DELAYED_WRITEBACK), corresponding worker func won't quit until
the number of items < BTRFS_DELAYED_BACKGROUND / 2. So, it is possible that
the func occupies CPU infinitely (up to 30sec in my experiments): while the
func is trying to drain the list, the user activity may add more and more
items to the list.

The patch fixes both problems in straightforward way: refuse queuing too
many works in btrfs_wq_run_delayed_node and bail out of worker func if
at least BTRFS_DELAYED_WRITEBACK items are processed.

Changed in v2: remove support of thresh == NO_THRESHOLD.

Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com>
Signed-off-by: Chris Mason <clm@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 fs/btrfs/async-thread.c  |   14 ++++++++++++++
 fs/btrfs/async-thread.h  |    1 +
 fs/btrfs/delayed-inode.c |    6 ++++--
 3 files changed, 19 insertions(+), 2 deletions(-)

--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -70,6 +70,20 @@ void btrfs_##name(struct work_struct *ar
 	normal_work_helper(work);					\
 }
 
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq)
+{
+	/*
+	 * We could compare wq->normal->pending with num_online_cpus()
+	 * to support "thresh == NO_THRESHOLD" case, but it requires
+	 * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's
+	 * postpone it until someone needs the support of that case.
+	 */
+	if (wq->normal->thresh == NO_THRESHOLD)
+		return false;
+
+	return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2;
+}
+
 BTRFS_WORK_HELPER(worker_helper);
 BTRFS_WORK_HELPER(delalloc_helper);
 BTRFS_WORK_HELPER(flush_delalloc_helper);
--- a/fs/btrfs/async-thread.h
+++ b/fs/btrfs/async-thread.h
@@ -80,4 +80,5 @@ void btrfs_queue_work(struct btrfs_workq
 void btrfs_destroy_workqueue(struct btrfs_workqueue *wq);
 void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
 void btrfs_set_work_high_priority(struct btrfs_work *work);
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq);
 #endif
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1375,7 +1375,8 @@ release_path:
 	total_done++;
 
 	btrfs_release_prepared_delayed_node(delayed_node);
-	if (async_work->nr == 0 || total_done < async_work->nr)
+	if ((async_work->nr == 0 && total_done < BTRFS_DELAYED_WRITEBACK) ||
+	    total_done < async_work->nr)
 		goto again;
 
 free_path:
@@ -1391,7 +1392,8 @@ static int btrfs_wq_run_delayed_node(str
 {
 	struct btrfs_async_delayed_work *async_work;
 
-	if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
+	if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND ||
+	    btrfs_workqueue_normal_congested(fs_info->delayed_workers))
 		return 0;
 
 	async_work = kmalloc(sizeof(*async_work), GFP_NOFS);



  reply	other threads:[~2017-01-04 20:47 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20170104205105epcas5p4dfb9f8f2e2771bc19858b096e326c051@epcas5p4.samsung.com>
2017-01-04 20:46 ` [PATCH 4.4 00/60] 4.4.40-stable review Greg Kroah-Hartman
2017-01-04 20:46   ` Greg Kroah-Hartman [this message]
2017-01-04 20:46   ` [PATCH 4.4 02/60] Btrfs: fix tree search logic when replaying directory entry deletes Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 03/60] btrfs: store and load values of stripes_min/stripes_max in balance status item Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 04/60] Btrfs: fix qgroup rescan worker initialization Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 05/60] USB: serial: option: add support for Telit LE922A PIDs 0x1040, 0x1041 Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 06/60] USB: serial: option: add dlink dwm-158 Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 07/60] USB: serial: kl5kusb105: fix open error path Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 08/60] USB: cdc-acm: add device id for GW Instek AFG-125 Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 09/60] usb: hub: Fix auto-remount of safely removed or ejected USB-3 devices Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 10/60] usb: gadget: f_uac2: fix error handling at afunc_bind Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 11/60] usb: gadget: composite: correctly initialize ep->maxpacket Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 12/60] USB: UHCI: report non-PME wakeup signalling for Intel hardware Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 13/60] ALSA: usb-audio: Add QuickCam Communicate Deluxe/S7500 to volume_control_quirks Greg Kroah-Hartman
2017-01-04 20:46   ` [PATCH 4.4 14/60] ALSA: hiface: Fix M2Tech hiFace driver sampling rate change Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 15/60] ALSA: hda/ca0132 - Add quirk for Alienware 15 R2 2016 Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 16/60] ALSA: hda - ignore the assoc and seq when comparing pin configurations Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 17/60] ALSA: hda - fix headset-mic problem on a Dell laptop Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 18/60] ALSA: hda - Gate the mic jack on HP Z1 Gen3 AiO Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 19/60] ALSA: hda: when comparing pin configurations, ignore assoc in addition to seq Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 20/60] clk: ti: omap36xx: Work around sprz319 advisory 2.1 Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 21/60] Btrfs: fix memory leak in reading btree blocks Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 22/60] Btrfs: bail out if block group has different mixed flag Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 23/60] Btrfs: return gracefully from balance if fs tree is corrupted Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 24/60] Btrfs: dont leak reloc root nodes on error Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 25/60] Btrfs: fix memory leak in do_walk_down Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 26/60] Btrfs: dont BUG() during drop snapshot Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 27/60] btrfs: make file clone aware of fatal signals Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 28/60] block_dev: dont test bdev->bd_contains when it is not stable Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 29/60] mm: Add a user_ns owner to mm_struct and fix ptrace permission checks Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 30/60] ptrace: Capture the ptracers creds not PT_PTRACE_CAP Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 32/60] ext4: fix mballoc breakage with 64k block size Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 33/60] ext4: fix stack memory corruption " Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 34/60] ext4: use more strict checks for inodes_per_block on mount Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 35/60] ext4: fix in-superblock mount options processing Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 36/60] ext4: add sanity checking to count_overhead() Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 37/60] ext4: reject inodes with negative size Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 38/60] ext4: return -ENOMEM instead of success Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 39/60] ext4: do not perform data journaling when data is encrypted Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 40/60] f2fs: set ->owner for debugfs status files file_operations Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 41/60] loop: return proper error from loop_queue_rq() Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 42/60] mm/vmscan.c: set correct defer count for shrinker Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 43/60] fs: exec: apply CLOEXEC before changing dumpable task flags Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 44/60] exec: Ensure mm->user_ns contains the execed files Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 45/60] usb: gadget: composite: always set ep->mult to a sensible value Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 46/60] blk-mq: Do not invoke .queue_rq() for a stopped queue Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 47/60] dm flakey: return -EINVAL on interval bounds error in flakey_ctr() Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 48/60] dm crypt: mark key as invalid until properly loaded Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 49/60] dm space map metadata: fix struct sm_metadata leak on failed create Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 50/60] ASoC: intel: Fix crash at suspend/resume without card registration Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 51/60] CIFS: Fix a possible memory corruption during reconnect Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 52/60] CIFS: Fix missing nls unload in smb2_reconnect() Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 53/60] CIFS: Fix a possible memory corruption in push locks Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 54/60] kernel/watchdog: use nmi registers snapshot in hardlockup handler Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 55/60] kernel/debug/debug_core.c: more properly delay for secondary CPUs Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 56/60] tpm xen: Remove bogus tpm_chip_unregister Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 57/60] xen/gntdev: Use VM_MIXEDMAP instead of VM_IO to avoid NUMA balancing Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 58/60] arm/xen: Use alloc_percpu rather than __alloc_percpu Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 59/60] xfs: set AGI buffer type in xlog_recover_clear_agi_bucket Greg Kroah-Hartman
2017-01-04 20:47   ` [PATCH 4.4 60/60] driver core: fix race between creating/querying glue dir and its cleanup Greg Kroah-Hartman
2017-01-05  0:42   ` [PATCH 4.4 00/60] 4.4.40-stable review Shuah Khan
2017-01-05  5:25   ` Guenter Roeck
2017-01-05 15:33   ` Guillaume Nault
2017-01-05 20:35     ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170104200705.689931149@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=clm@fb.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpatlasov@virtuozzo.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).