Bug 190751
Summary: | reference leak in percpu_ref_tryget and percpu_ref_tryget_live | ||
---|---|---|---|
Product: | IO/Storage | Reporter: | Douglas Miller (dougmill) |
Component: | Block Layer | Assignee: | Jens Axboe (axboe) |
Status: | RESOLVED CODE_FIX | ||
Severity: | high | CC: | gpiccoli, mniyer |
Priority: | P1 | ||
Hardware: | PPC-64 | ||
OS: | Linux | ||
Kernel Version: | 4.9 | Subsystem: | |
Regression: | No | Bisected commit-id: |
Description
Douglas Miller
2016-12-20 13:54:31 UTC
The above stack trace is from RHEL 7.3. This can also be reproduce by simply reading a (multi-queue) block device while off/onlining CPUs. For example, the following script reproduces it on a PPC64 system with an NVMe drive: #!/bin/bash if [[ ${#} -eq 0 ]]; then ${0} breaker & while true; do dd if=/dev/nvme0n1 bs=1024k of=/dev/null done elif [[ ${1} == "breaker" ]]; then while true; do ppc64_cpu --smt=off sleep 5 ppc64_cpu --smt=on sleep 5 done fi The problem usually reproduces in a few minutes, although sometimes it has taken a few hours. I suspect the problem is related to the changes in commit 71f79fb3179e69b0c1448a2101a866d871c66e7f. If I revert blk_mq_timeout_work() to use blk_queue_enter(q, true) the hang is no longer seen, however the original deadlock that Gabriel fixed will return, so we cannot simply revert the patch. I am seeing this hang on 4.10.0-rc5. I might see the bug here. percpu_ref_tryget() calls atomic_long_inc_not_zero() in the case we're seeing, which would change the count from 8000000000000000 to 8000000000000001 and return 8000000000000000. But, percpu_ref_tryget() captures the return value as an int, not long, and returns it as a true/false indicating whether or not the increment took place. But, because it stripped off the high bits, it returns "0" indicating the increment did not take place when in fact the increment *did* take place because the true counter value was 8000000000000000 and not 00000000. This looks like a bug in percpu_ref_tryget*() routines. Patch submitted https://lkml.org/lkml/2017/1/27/810 V3 patch is now staged for 4.10 and next: https://git.kernel.org/cgit/linux/kernel/git/tj/percpu.git/commit/?h=for-next&id=966d2b04e070bc040319aaebfec09e0144dc3341 Commit is now in kernel/git/torvalds/linux.git, closing. |