linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: John Sperbeck <jsperbeck@google.com>,
	Dennis Zhou <dennis@kernel.org>, Sasha Levin <sashal@kernel.org>,
	linux-mm@kvack.org, netdev@vger.kernel.org, bpf@vger.kernel.org
Subject: [PATCH AUTOSEL 4.19 043/141] percpu: remove spurious lock dependency between percpu and sched
Date: Sat,  1 Jun 2019 09:20:19 -0400	[thread overview]
Message-ID: <20190601132158.25821-43-sashal@kernel.org> (raw)
In-Reply-To: <20190601132158.25821-1-sashal@kernel.org>

From: John Sperbeck <jsperbeck@google.com>

[ Upstream commit 198790d9a3aeaef5792d33a560020861126edc22 ]

In free_percpu() we sometimes call pcpu_schedule_balance_work() to
queue a work item (which does a wakeup) while holding pcpu_lock.
This creates an unnecessary lock dependency between pcpu_lock and
the scheduler's pi_lock.  There are other places where we call
pcpu_schedule_balance_work() without hold pcpu_lock, and this case
doesn't need to be different.

Moving the call outside the lock prevents the following lockdep splat
when running tools/testing/selftests/bpf/{test_maps,test_progs} in
sequence with lockdep enabled:

======================================================
WARNING: possible circular locking dependency detected
5.1.0-dbg-DEV #1 Not tainted
------------------------------------------------------
kworker/23:255/18872 is trying to acquire lock:
000000000bc79290 (&(&pool->lock)->rlock){-.-.}, at: __queue_work+0xb2/0x520

but task is already holding lock:
00000000e3e7a6aa (pcpu_lock){..-.}, at: free_percpu+0x36/0x260

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #4 (pcpu_lock){..-.}:
       lock_acquire+0x9e/0x180
       _raw_spin_lock_irqsave+0x3a/0x50
       pcpu_alloc+0xfa/0x780
       __alloc_percpu_gfp+0x12/0x20
       alloc_htab_elem+0x184/0x2b0
       __htab_percpu_map_update_elem+0x252/0x290
       bpf_percpu_hash_update+0x7c/0x130
       __do_sys_bpf+0x1912/0x1be0
       __x64_sys_bpf+0x1a/0x20
       do_syscall_64+0x59/0x400
       entry_SYSCALL_64_after_hwframe+0x49/0xbe

-> #3 (&htab->buckets[i].lock){....}:
       lock_acquire+0x9e/0x180
       _raw_spin_lock_irqsave+0x3a/0x50
       htab_map_update_elem+0x1af/0x3a0

-> #2 (&rq->lock){-.-.}:
       lock_acquire+0x9e/0x180
       _raw_spin_lock+0x2f/0x40
       task_fork_fair+0x37/0x160
       sched_fork+0x211/0x310
       copy_process.part.43+0x7b1/0x2160
       _do_fork+0xda/0x6b0
       kernel_thread+0x29/0x30
       rest_init+0x22/0x260
       arch_call_rest_init+0xe/0x10
       start_kernel+0x4fd/0x520
       x86_64_start_reservations+0x24/0x26
       x86_64_start_kernel+0x6f/0x72
       secondary_startup_64+0xa4/0xb0

-> #1 (&p->pi_lock){-.-.}:
       lock_acquire+0x9e/0x180
       _raw_spin_lock_irqsave+0x3a/0x50
       try_to_wake_up+0x41/0x600
       wake_up_process+0x15/0x20
       create_worker+0x16b/0x1e0
       workqueue_init+0x279/0x2ee
       kernel_init_freeable+0xf7/0x288
       kernel_init+0xf/0x180
       ret_from_fork+0x24/0x30

-> #0 (&(&pool->lock)->rlock){-.-.}:
       __lock_acquire+0x101f/0x12a0
       lock_acquire+0x9e/0x180
       _raw_spin_lock+0x2f/0x40
       __queue_work+0xb2/0x520
       queue_work_on+0x38/0x80
       free_percpu+0x221/0x260
       pcpu_freelist_destroy+0x11/0x20
       stack_map_free+0x2a/0x40
       bpf_map_free_deferred+0x3c/0x50
       process_one_work+0x1f7/0x580
       worker_thread+0x54/0x410
       kthread+0x10f/0x150
       ret_from_fork+0x24/0x30

other info that might help us debug this:

Chain exists of:
  &(&pool->lock)->rlock --> &htab->buckets[i].lock --> pcpu_lock

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(pcpu_lock);
                               lock(&htab->buckets[i].lock);
                               lock(pcpu_lock);
  lock(&(&pool->lock)->rlock);

 *** DEADLOCK ***

3 locks held by kworker/23:255/18872:
 #0: 00000000b36a6e16 ((wq_completion)events){+.+.},
     at: process_one_work+0x17a/0x580
 #1: 00000000dfd966f0 ((work_completion)(&map->work)){+.+.},
     at: process_one_work+0x17a/0x580
 #2: 00000000e3e7a6aa (pcpu_lock){..-.},
     at: free_percpu+0x36/0x260

stack backtrace:
CPU: 23 PID: 18872 Comm: kworker/23:255 Not tainted 5.1.0-dbg-DEV #1
Hardware name: ...
Workqueue: events bpf_map_free_deferred
Call Trace:
 dump_stack+0x67/0x95
 print_circular_bug.isra.38+0x1c6/0x220
 check_prev_add.constprop.50+0x9f6/0xd20
 __lock_acquire+0x101f/0x12a0
 lock_acquire+0x9e/0x180
 _raw_spin_lock+0x2f/0x40
 __queue_work+0xb2/0x520
 queue_work_on+0x38/0x80
 free_percpu+0x221/0x260
 pcpu_freelist_destroy+0x11/0x20
 stack_map_free+0x2a/0x40
 bpf_map_free_deferred+0x3c/0x50
 process_one_work+0x1f7/0x580
 worker_thread+0x54/0x410
 kthread+0x10f/0x150
 ret_from_fork+0x24/0x30

Signed-off-by: John Sperbeck <jsperbeck@google.com>
Signed-off-by: Dennis Zhou <dennis@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 mm/percpu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/mm/percpu.c b/mm/percpu.c
index 41e58f3d8fbf2..c66149ce1fe6a 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1721,6 +1721,7 @@ void free_percpu(void __percpu *ptr)
 	struct pcpu_chunk *chunk;
 	unsigned long flags;
 	int off;
+	bool need_balance = false;
 
 	if (!ptr)
 		return;
@@ -1742,7 +1743,7 @@ void free_percpu(void __percpu *ptr)
 
 		list_for_each_entry(pos, &pcpu_slot[pcpu_nr_slots - 1], list)
 			if (pos != chunk) {
-				pcpu_schedule_balance_work();
+				need_balance = true;
 				break;
 			}
 	}
@@ -1750,6 +1751,9 @@ void free_percpu(void __percpu *ptr)
 	trace_percpu_free_percpu(chunk->base_addr, off, ptr);
 
 	spin_unlock_irqrestore(&pcpu_lock, flags);
+
+	if (need_balance)
+		pcpu_schedule_balance_work();
 }
 EXPORT_SYMBOL_GPL(free_percpu);
 
-- 
2.20.1


  parent reply	other threads:[~2019-06-01 13:35 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-01 13:19 [PATCH AUTOSEL 4.19 001/141] rapidio: fix a NULL pointer dereference when create_workqueue() fails Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 002/141] fs/fat/file.c: issue flush after the writeback of FAT Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 003/141] sysctl: return -EINVAL if val violates minmax Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 004/141] ipc: prevent lockup on alloc_msg and free_msg Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 005/141] drm/pl111: Initialize clock spinlock early Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 006/141] ARM: prevent tracing IPI_CPU_BACKTRACE Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 007/141] mm/hmm: select mmu notifier when selecting HMM Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 008/141] hugetlbfs: on restore reserve error path retain subpool reservation Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 009/141] mem-hotplug: fix node spanned pages when we have a node with only ZONE_MOVABLE Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 010/141] mm/cma.c: fix crash on CMA allocation if bitmap allocation fails Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 011/141] initramfs: free initrd memory if opening /initrd.image fails Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 012/141] mm/cma.c: fix the bitmap status to show failed allocation reason Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 013/141] mm: page_mkclean vs MADV_DONTNEED race Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 014/141] mm/cma_debug.c: fix the break condition in cma_maxchunk_get() Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 015/141] mm/slab.c: fix an infinite loop in leaks_show() Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 016/141] kernel/sys.c: prctl: fix false positive in validate_prctl_map() Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 017/141] thermal: rcar_gen3_thermal: disable interrupt in .remove Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 018/141] drivers: thermal: tsens: Don't print error message on -EPROBE_DEFER Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 019/141] mfd: tps65912-spi: Add missing of table registration Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 020/141] mfd: intel-lpss: Set the device in reset state when init Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 021/141] drm/nouveau/disp/dp: respect sink limits when selecting failsafe link configuration Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 022/141] mfd: twl6040: Fix device init errors for ACCCTL register Sasha Levin
2019-06-01 13:19 ` [PATCH AUTOSEL 4.19 023/141] perf/x86/intel: Allow PEBS multi-entry in watermark mode Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 024/141] drm/nouveau/kms/gf119-gp10x: push HeadSetControlOutputResource() mthd when encoders change Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 025/141] drm/bridge: adv7511: Fix low refresh rate selection Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 026/141] objtool: Don't use ignore flag for fake jumps Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 027/141] drm/nouveau/kms/gv100-: fix spurious window immediate interlocks Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 028/141] bpf: fix undefined behavior in narrow load handling Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 029/141] EDAC/mpc85xx: Prevent building as a module Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 030/141] NFS4: Fix v4.0 client state corruption when mount Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 031/141] pwm: meson: Use the spin-lock only to protect register modifications Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 032/141] mailbox: stm32-ipcc: check invalid irq Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 033/141] ntp: Allow TAI-UTC offset to be set to zero Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 034/141] f2fs: fix to avoid panic in do_recover_data() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 035/141] f2fs: fix to avoid panic in f2fs_inplace_write_data() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 036/141] f2fs: fix to avoid panic in f2fs_remove_inode_page() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 037/141] f2fs: fix to do sanity check on free nid Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 038/141] f2fs: fix to clear dirty inode in error path of f2fs_iget() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 039/141] f2fs: fix to avoid panic in dec_valid_block_count() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 040/141] f2fs: fix to use inline space only if inline_xattr is enable Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 041/141] f2fs: fix to do sanity check on valid block count of segment Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 042/141] f2fs: fix to do checksum even if inode page is uptodate Sasha Levin
2019-06-01 13:20 ` Sasha Levin [this message]
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 044/141] tracing: Fix partial reading of trace event's id file Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 045/141] configfs: fix possible use-after-free in configfs_register_group Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 046/141] uml: fix a boot splat wrt use of cpu_all_mask Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 047/141] PCI: dwc: Free MSI in dw_pcie_host_init() error path Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 048/141] PCI: dwc: Free MSI IRQ page in dw_pcie_free_msi() Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 049/141] ovl: do not generate duplicate fsnotify events for "fake" path Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 050/141] mmc: mmci: Prevent polling for busy detection in IRQ context Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 051/141] netfilter: nf_flow_table: fix missing error check for rhashtable_insert_fast Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 052/141] netfilter: nf_conntrack_h323: restore boundary check correctness Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 053/141] mips: Make sure dt memory regions are valid Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 054/141] netfilter: nf_tables: fix base chain stat rcu_dereference usage Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 055/141] watchdog: Use depends instead of select for pretimeout governors Sasha Levin
2019-06-01 13:20 ` [PATCH AUTOSEL 4.19 056/141] watchdog: imx2_wdt: Fix set_timeout for big timeout values Sasha Levin

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=20190601132158.25821-43-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=dennis@kernel.org \
    --cc=jsperbeck@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=netdev@vger.kernel.org \
    --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).