From: Josef Bacik <josef(a)toxicpanda.com>
Commit 38e3eebff643db725633657d1d87a3be019d1018.
Qgroups will do the old roots lookup at delayed ref time, which could be
while walking down the extent root while running a delayed ref. This
should be fine, except we specifically lock eb's in the backref walking
code irrespective of path->skip_locking, which deadlocks the system.
Fix up the backref code to honor path->skip_locking, nobody will be
modifying the commit_root when we're searching so it's completely safe
to do.
This happens since fb235dc06fac ("btrfs: qgroup: Move half of the qgroup
accounting time out of commit trans"), kernel may lockup with quota
enabled.
There is one backref trace triggered by snapshot dropping along with
write operation in the source subvolume. The example can be reliably
reproduced:
btrfs-cleaner D 0 4062 2 0x80000000
Call Trace:
schedule+0x32/0x90
btrfs_tree_read_lock+0x93/0x130 [btrfs]
find_parent_nodes+0x29b/0x1170 [btrfs]
btrfs_find_all_roots_safe+0xa8/0x120 [btrfs]
btrfs_find_all_roots+0x57/0x70 [btrfs]
btrfs_qgroup_trace_extent_post+0x37/0x70 [btrfs]
btrfs_qgroup_trace_leaf_items+0x10b/0x140 [btrfs]
btrfs_qgroup_trace_subtree+0xc8/0xe0 [btrfs]
do_walk_down+0x541/0x5e3 [btrfs]
walk_down_tree+0xab/0xe7 [btrfs]
btrfs_drop_snapshot+0x356/0x71a [btrfs]
btrfs_clean_one_deleted_snapshot+0xb8/0xf0 [btrfs]
cleaner_kthread+0x12b/0x160 [btrfs]
kthread+0x112/0x130
ret_from_fork+0x27/0x50
When dropping snapshots with qgroup enabled, we will trigger backref
walk.
However such backref walk at that timing is pretty dangerous, as if one
of the parent nodes get WRITE locked by other thread, we could cause a
dead lock.
For example:
FS 260 FS 261 (Dropped)
node A node B
/ \ / \
node C node D node E
/ \ / \ / \
leaf F|leaf G|leaf H|leaf I|leaf J|leaf K
The lock sequence would be:
Thread A (cleaner) | Thread B (other writer)
-----------------------------------------------------------------------
write_lock(B) |
write_lock(D) |
^^^ called by walk_down_tree() |
| write_lock(A)
| write_lock(D) << Stall
read_lock(H) << for backref walk |
read_lock(D) << lock owner is |
the same thread A |
so read lock is OK |
read_lock(A) << Stall |
So thread A hold write lock D, and needs read lock A to unlock.
While thread B holds write lock A, while needs lock D to unlock.
This will cause a deadlock.
This is not only limited to snapshot dropping case. As the backref
walk, even only happens on commit trees, is breaking the normal top-down
locking order, makes it deadlock prone.
Fixes: fb235dc06fac ("btrfs: qgroup: Move half of the qgroup accounting time out of commit trans")
CC: stable(a)vger.kernel.org # 4.14
Reported-and-tested-by: David Sterba <dsterba(a)suse.com>
Reported-by: Filipe Manana <fdmanana(a)suse.com>
Reviewed-by: Qu Wenruo <wqu(a)suse.com>
Signed-off-by: Josef Bacik <josef(a)toxicpanda.com>
Reviewed-by: Filipe Manana <fdmanana(a)suse.com>
[ rebase to latest branch and fix lock assert bug in btrfs/007 ]
Signed-off-by: Qu Wenruo <wqu(a)suse.com>
[ copy logs and deadlock analysis from Qu's patch ]
Signed-off-by: David Sterba <dsterba(a)suse.com>
---
fs/btrfs/backref.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 196503d8c993..e4d5e6eae409 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -718,7 +718,7 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info,
* read tree blocks and add keys where required.
*/
static int add_missing_keys(struct btrfs_fs_info *fs_info,
- struct preftrees *preftrees)
+ struct preftrees *preftrees, bool lock)
{
struct prelim_ref *ref;
struct extent_buffer *eb;
@@ -742,12 +742,14 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info,
free_extent_buffer(eb);
return -EIO;
}
- btrfs_tree_read_lock(eb);
+ if (lock)
+ btrfs_tree_read_lock(eb);
if (btrfs_header_level(eb) == 0)
btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0);
else
btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0);
- btrfs_tree_read_unlock(eb);
+ if (lock)
+ btrfs_tree_read_unlock(eb);
free_extent_buffer(eb);
prelim_ref_insert(fs_info, &preftrees->indirect, ref, NULL);
cond_resched();
@@ -1228,7 +1230,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
btrfs_release_path(path);
- ret = add_missing_keys(fs_info, &preftrees);
+ ret = add_missing_keys(fs_info, &preftrees, path->skip_locking == 0);
if (ret)
goto out;
@@ -1288,11 +1290,14 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
ret = -EIO;
goto out;
}
- btrfs_tree_read_lock(eb);
- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+ if (!path->skip_locking) {
+ btrfs_tree_read_lock(eb);
+ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+ }
ret = find_extent_in_eb(eb, bytenr,
*extent_item_pos, &eie);
- btrfs_tree_read_unlock_blocking(eb);
+ if (!path->skip_locking)
+ btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb);
if (ret < 0)
goto out;
--
2.21.0
Hello,
We ran automated tests on a patchset that was proposed for merging into this
kernel tree. The patches were applied to:
Kernel repo: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Commit: 8b2fc0058255 - Linux 4.19.46
The results of these automated tests are provided below.
Overall result: PASSED
Merge: OK
Compile: OK
Tests: OK
Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.
,-. ,-.
( C ) ( K ) Continuous
`-',-.`-' Kernel
( I ) Integration
`-'
______________________________________________________________________________
Merge testing
-------------
We cloned this repository and checked out the following commit:
Repo: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Commit: 8b2fc0058255 - Linux 4.19.46
We then merged the patchset with `git am`:
x86-hide-the-int3_emulate_call-jmp-functions-from-uml.patch
ext4-do-not-delete-unlinked-inode-from-orphan-list-on-failed-truncate.patch
ext4-wait-for-outstanding-dio-during-truncate-in-nojournal-mode.patch
f2fs-fix-use-of-number-of-devices.patch
kvm-x86-fix-return-value-for-reserved-efer.patch
bio-fix-improper-use-of-smp_mb__before_atomic.patch
sbitmap-fix-improper-use-of-smp_mb__before_atomic.patch
revert-scsi-sd-keep-disk-read-only-when-re-reading-partition.patch
crypto-vmx-ctr-always-increment-iv-as-quadword.patch
mmc-sdhci-iproc-cygnus-set-no_hispd-bit-to-fix-hs50-data-hold-time-problem.patch
mmc-sdhci-iproc-set-no_hispd-bit-to-fix-hs50-data-hold-time-problem.patch
kvm-svm-avic-fix-off-by-one-in-checking-host-apic-id.patch
libnvdimm-pmem-bypass-config_hardened_usercopy-overhead.patch
arm64-kernel-kaslr-reduce-module-randomization-range-to-2-gb.patch
arm64-iommu-handle-non-remapped-addresses-in-mmap-and-get_sgtable.patch
gfs2-fix-sign-extension-bug-in-gfs2_update_stats.patch
btrfs-don-t-double-unlock-on-error-in-btrfs_punch_hole.patch
btrfs-do-not-abort-transaction-at-btrfs_update_root-after-failure-to-cow-path.patch
btrfs-avoid-fallback-to-transaction-commit-during-fsync-of-files-with-holes.patch
btrfs-fix-race-between-ranged-fsync-and-writeback-of-adjacent-ranges.patch
btrfs-sysfs-fix-error-path-kobject-memory-leak.patch
btrfs-sysfs-don-t-leak-memory-when-failing-add-fsid.patch
udlfb-fix-some-inconsistent-null-checking.patch
fbdev-fix-divide-error-in-fb_var_to_videomode.patch
nfsv4.2-fix-unnecessary-retry-in-nfs4_copy_file_range.patch
nfsv4.1-fix-incorrect-return-value-in-copy_file_range.patch
bpf-add-bpf_jit_limit-knob-to-restrict-unpriv-allocations.patch
brcmfmac-assure-ssid-length-from-firmware-is-limited.patch
brcmfmac-add-subtype-check-for-event-handling-in-data-path.patch
arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch
btrfs-honor-path-skip_locking-in-backref-code.patch
Compile testing
---------------
We compiled the kernel for 4 architectures:
aarch64:
build options: -j25 INSTALL_MOD_STRIP=1 targz-pkg
configuration: https://artifacts.cki-project.org/builds/aarch64/kernel-stable_queue_4.19-a…
kernel build: https://artifacts.cki-project.org/builds/aarch64/kernel-stable_queue_4.19-a…
ppc64le:
build options: -j25 INSTALL_MOD_STRIP=1 targz-pkg
configuration: https://artifacts.cki-project.org/builds/ppc64le/kernel-stable_queue_4.19-p…
kernel build: https://artifacts.cki-project.org/builds/ppc64le/kernel-stable_queue_4.19-p…
s390x:
build options: -j25 INSTALL_MOD_STRIP=1 targz-pkg
configuration: https://artifacts.cki-project.org/builds/s390x/kernel-stable_queue_4.19-s39…
kernel build: https://artifacts.cki-project.org/builds/s390x/kernel-stable_queue_4.19-s39…
x86_64:
build options: -j25 INSTALL_MOD_STRIP=1 targz-pkg
configuration: https://artifacts.cki-project.org/builds/x86_64/kernel-stable_queue_4.19-x8…
kernel build: https://artifacts.cki-project.org/builds/x86_64/kernel-stable_queue_4.19-x8…
Hardware testing
----------------
We booted each kernel and ran the following tests:
aarch64:
Host 1:
✅ Boot test [0]
✅ xfstests: ext4 [1]
✅ selinux-policy: serge-testsuite [2]
Host 2:
✅ Boot test [0]
✅ LTP lite [3]
✅ Loopdev Sanity [4]
✅ AMTU (Abstract Machine Test Utility) [5]
✅ audit: audit testsuite test [6]
✅ httpd: mod_ssl smoke sanity [7]
✅ iotop: sanity [8]
✅ tuned: tune-processes-through-perf [9]
✅ Usex - version 1.9-29 [10]
✅ stress: stress-ng [11]
🚧 ✅ Networking socket: fuzz [12]
ppc64le:
Host 1:
✅ Boot test [0]
✅ xfstests: ext4 [1]
✅ selinux-policy: serge-testsuite [2]
Host 2:
✅ Boot test [0]
✅ LTP lite [3]
✅ Loopdev Sanity [4]
✅ AMTU (Abstract Machine Test Utility) [5]
✅ audit: audit testsuite test [6]
✅ httpd: mod_ssl smoke sanity [7]
✅ iotop: sanity [8]
✅ tuned: tune-processes-through-perf [9]
✅ Usex - version 1.9-29 [10]
✅ stress: stress-ng [11]
🚧 ✅ Networking socket: fuzz [12]
s390x:
Host 1:
✅ Boot test [0]
✅ selinux-policy: serge-testsuite [2]
Host 2:
✅ Boot test [0]
✅ LTP lite [3]
✅ Loopdev Sanity [4]
✅ audit: audit testsuite test [6]
✅ httpd: mod_ssl smoke sanity [7]
✅ iotop: sanity [8]
✅ tuned: tune-processes-through-perf [9]
✅ Usex - version 1.9-29 [10]
✅ stress: stress-ng [11]
🚧 ✅ Networking socket: fuzz [12]
x86_64:
Host 1:
✅ Boot test [0]
✅ xfstests: ext4 [1]
✅ selinux-policy: serge-testsuite [2]
Host 2:
✅ Boot test [0]
✅ LTP lite [3]
✅ Loopdev Sanity [4]
✅ AMTU (Abstract Machine Test Utility) [5]
✅ audit: audit testsuite test [6]
✅ httpd: mod_ssl smoke sanity [7]
✅ iotop: sanity [8]
✅ tuned: tune-processes-through-perf [9]
✅ Usex - version 1.9-29 [10]
✅ stress: stress-ng [11]
🚧 ✅ Networking socket: fuzz [12]
Test source:
💚 Pull requests are welcome for new tests or improvements to existing tests!
[0]: https://github.com/CKI-project/tests-beaker/archive/master.zip#distribution…
[1]: https://github.com/CKI-project/tests-beaker/archive/master.zip#/filesystems…
[2]: https://github.com/CKI-project/tests-beaker/archive/master.zip#/packages/se…
[3]: https://github.com/CKI-project/tests-beaker/archive/master.zip#distribution…
[4]: https://github.com/CKI-project/tests-beaker/archive/master.zip#filesystems/…
[5]: https://github.com/CKI-project/tests-beaker/archive/master.zip#misc/amtu
[6]: https://github.com/CKI-project/tests-beaker/archive/master.zip#packages/aud…
[7]: https://github.com/CKI-project/tests-beaker/archive/master.zip#packages/htt…
[8]: https://github.com/CKI-project/tests-beaker/archive/master.zip#packages/iot…
[9]: https://github.com/CKI-project/tests-beaker/archive/master.zip#packages/tun…
[10]: https://github.com/CKI-project/tests-beaker/archive/master.zip#standards/us…
[11]: https://github.com/CKI-project/tests-beaker/archive/master.zip#stress/stres…
[12]: https://github.com/CKI-project/tests-beaker/archive/master.zip#/networking/…
Waived tests (marked with 🚧)
-----------------------------
This test run included waived tests. Such tests are executed but their results
are not taken into account. Tests are waived when their results are not
reliable enough, e.g. when they're just introduced or are being fixed.
From: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
commit 53e947a0e1f7 ("ASoC: soc-core: merge card resources cleanup
method") merged cleanup method of snd_soc_instantiate_card() and
soc_cleanup_card_resources().
But, after this commit, if user uses unbind/bind to Component factor
drivers, Kernel might indicates refcount error at
soc_cleanup_card_resources().
The 1st reason is card->snd_card is still exist even though
snd_card_free() was called, but it is already cleaned.
We need to set NULL to it.
2nd is card->dapm and card create debugfs, but its dentry is still
exist even though it was removed. We need to set NULL to it.
Fixes: 53e947a0e1f7 ("ASoC: soc-core: merge card resources cleanup method")
Cc: stable(a)vger.kernel.org # for v5.1
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
---
sound/soc/soc-core.c | 7 ++++++-
sound/soc/soc-dapm.c | 3 +++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 46e3ab0..758159a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -228,7 +228,10 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
{
+ if (!card->debugfs_card_root)
+ return;
debugfs_remove_recursive(card->debugfs_card_root);
+ card->debugfs_card_root = NULL;
}
static void snd_soc_debugfs_init(void)
@@ -2034,8 +2037,10 @@ static void soc_check_tplg_fes(struct snd_soc_card *card)
static int soc_cleanup_card_resources(struct snd_soc_card *card)
{
/* free the ALSA card at first; this syncs with pending operations */
- if (card->snd_card)
+ if (card->snd_card) {
snd_card_free(card->snd_card);
+ card->snd_card = NULL;
+ }
/* remove and free each DAI */
soc_remove_dai_links(card);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 0382a47..5d9d767 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2192,7 +2192,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{
+ if (!dapm->debugfs_dapm)
+ return;
debugfs_remove_recursive(dapm->debugfs_dapm);
+ dapm->debugfs_dapm = NULL;
}
#else
--
2.7.4
Cc: stable(a)vger.kernel.org
Dear all,
It missed to send this patch to 'stable(a)vger.kernel.org'.
So, I add it to mailing list.
Regards,
Chanwoo Choi
On 19. 3. 13. 오후 9:22, Enric Balletbo i Serra wrote:
> The patch 23c7b54ca1cd: "PM / devfreq: Fix devfreq_add_device() when
> drivers are built as modules." leads to the following static checker
> warning:
>
> drivers/devfreq/devfreq.c:1043 governor_store()
> warn: 'governor' can also be NULL
>
> The reason is that the try_then_request_governor() function returns both
> error pointers and NULL. It should just return error pointers, so fix
> this by returning a ERR_PTR to the error intead of returning NULL.
>
> Fixes: 23c7b54ca1cd ("PM / devfreq: Fix devfreq_add_device() when drivers are built as modules.")
> Reported-by: Dan Carpenter <dan.carpenter(a)oracle.com>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo(a)collabora.com>
> Reviewed-by: Chanwoo Choi <cw00.choi(a)samsung.com>
> ---
> Hi,
>
> This is a resend of [1] as seems that got lost at some point and I just
> noticed that was never merged.
>
> Thanks,
> Enric
>
> [1] https://lkml.org/lkml/2018/10/16/744
>
>
> drivers/devfreq/devfreq.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 0ae3de76833b..839621b044f4 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -228,7 +228,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
> * if is not found. This can happen when both drivers (the governor driver
> * and the driver that call devfreq_add_device) are built as modules.
> * devfreq_list_lock should be held by the caller. Returns the matched
> - * governor's pointer.
> + * governor's pointer or an error pointer.
> */
> static struct devfreq_governor *try_then_request_governor(const char *name)
> {
> @@ -254,7 +254,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
> /* Restore previous state before return */
> mutex_lock(&devfreq_list_lock);
> if (err)
> - return NULL;
> + return ERR_PTR(err);
>
> governor = find_devfreq_governor(name);
> }
>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
From: Josef Bacik <josef(a)toxicpanda.com>
Commit 38e3eebff643db725633657d1d87a3be019d1018.
Qgroups will do the old roots lookup at delayed ref time, which could be
while walking down the extent root while running a delayed ref. This
should be fine, except we specifically lock eb's in the backref walking
code irrespective of path->skip_locking, which deadlocks the system.
Fix up the backref code to honor path->skip_locking, nobody will be
modifying the commit_root when we're searching so it's completely safe
to do.
This happens since fb235dc06fac ("btrfs: qgroup: Move half of the qgroup
accounting time out of commit trans"), kernel may lockup with quota
enabled.
There is one backref trace triggered by snapshot dropping along with
write operation in the source subvolume. The example can be reliably
reproduced:
btrfs-cleaner D 0 4062 2 0x80000000
Call Trace:
schedule+0x32/0x90
btrfs_tree_read_lock+0x93/0x130 [btrfs]
find_parent_nodes+0x29b/0x1170 [btrfs]
btrfs_find_all_roots_safe+0xa8/0x120 [btrfs]
btrfs_find_all_roots+0x57/0x70 [btrfs]
btrfs_qgroup_trace_extent_post+0x37/0x70 [btrfs]
btrfs_qgroup_trace_leaf_items+0x10b/0x140 [btrfs]
btrfs_qgroup_trace_subtree+0xc8/0xe0 [btrfs]
do_walk_down+0x541/0x5e3 [btrfs]
walk_down_tree+0xab/0xe7 [btrfs]
btrfs_drop_snapshot+0x356/0x71a [btrfs]
btrfs_clean_one_deleted_snapshot+0xb8/0xf0 [btrfs]
cleaner_kthread+0x12b/0x160 [btrfs]
kthread+0x112/0x130
ret_from_fork+0x27/0x50
When dropping snapshots with qgroup enabled, we will trigger backref
walk.
However such backref walk at that timing is pretty dangerous, as if one
of the parent nodes get WRITE locked by other thread, we could cause a
dead lock.
For example:
FS 260 FS 261 (Dropped)
node A node B
/ \ / \
node C node D node E
/ \ / \ / \
leaf F|leaf G|leaf H|leaf I|leaf J|leaf K
The lock sequence would be:
Thread A (cleaner) | Thread B (other writer)
-----------------------------------------------------------------------
write_lock(B) |
write_lock(D) |
^^^ called by walk_down_tree() |
| write_lock(A)
| write_lock(D) << Stall
read_lock(H) << for backref walk |
read_lock(D) << lock owner is |
the same thread A |
so read lock is OK |
read_lock(A) << Stall |
So thread A hold write lock D, and needs read lock A to unlock.
While thread B holds write lock A, while needs lock D to unlock.
This will cause a deadlock.
This is not only limited to snapshot dropping case. As the backref
walk, even only happens on commit trees, is breaking the normal top-down
locking order, makes it deadlock prone.
Fixes: fb235dc06fac ("btrfs: qgroup: Move half of the qgroup accounting time out of commit trans")
CC: stable(a)vger.kernel.org # 5.0
Reported-and-tested-by: David Sterba <dsterba(a)suse.com>
Reported-by: Filipe Manana <fdmanana(a)suse.com>
Reviewed-by: Qu Wenruo <wqu(a)suse.com>
Signed-off-by: Josef Bacik <josef(a)toxicpanda.com>
Reviewed-by: Filipe Manana <fdmanana(a)suse.com>
[ rebase to latest branch and fix lock assert bug in btrfs/007 ]
Signed-off-by: Qu Wenruo <wqu(a)suse.com>
[ copy logs and deadlock analysis from Qu's patch ]
[ solve conflicts and backport to linux-5.0.y ]
Signed-off-by: David Sterba <dsterba(a)suse.com>
---
fs/btrfs/backref.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index ef66db38cedb..efe4d4080a21 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -712,7 +712,7 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info,
* read tree blocks and add keys where required.
*/
static int add_missing_keys(struct btrfs_fs_info *fs_info,
- struct preftrees *preftrees)
+ struct preftrees *preftrees, bool lock)
{
struct prelim_ref *ref;
struct extent_buffer *eb;
@@ -737,12 +737,14 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info,
free_extent_buffer(eb);
return -EIO;
}
- btrfs_tree_read_lock(eb);
+ if (lock)
+ btrfs_tree_read_lock(eb);
if (btrfs_header_level(eb) == 0)
btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0);
else
btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0);
- btrfs_tree_read_unlock(eb);
+ if (lock)
+ btrfs_tree_read_unlock(eb);
free_extent_buffer(eb);
prelim_ref_insert(fs_info, &preftrees->indirect, ref, NULL);
cond_resched();
@@ -1227,7 +1229,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
btrfs_release_path(path);
- ret = add_missing_keys(fs_info, &preftrees);
+ ret = add_missing_keys(fs_info, &preftrees, path->skip_locking == 0);
if (ret)
goto out;
@@ -1288,11 +1290,14 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
ret = -EIO;
goto out;
}
- btrfs_tree_read_lock(eb);
- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+ if (!path->skip_locking) {
+ btrfs_tree_read_lock(eb);
+ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+ }
ret = find_extent_in_eb(eb, bytenr,
*extent_item_pos, &eie, ignore_offset);
- btrfs_tree_read_unlock_blocking(eb);
+ if (!path->skip_locking)
+ btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb);
if (ret < 0)
goto out;
--
2.21.0