Skip to content

Commit 5b8418b

Browse files
committed
Revert "btrfs: turn name_cache radix tree into XArray in send_ctx"
This reverts commit 4076942. Revert the xarray conversion, there's a problem with potential sleep-inside-spinlock [1] when calling xa_insert that triggers GFP_NOFS allocation. The radix tree used the preloading mechanism to avoid sleeping but this is not available in xarray. Conversion from spin lock to mutex is possible but at time of rc6 is riskier than a clean revert. [1] https://lore.kernel.org/linux-btrfs/cover.1657097693.git.fdmanana@suse.com/ Reported-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 01cd390 commit 5b8418b

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

fs/btrfs/send.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/mount.h>
1111
#include <linux/xattr.h>
1212
#include <linux/posix_acl_xattr.h>
13+
#include <linux/radix-tree.h>
1314
#include <linux/vmalloc.h>
1415
#include <linux/string.h>
1516
#include <linux/compat.h>
@@ -127,7 +128,7 @@ struct send_ctx {
127128
struct list_head new_refs;
128129
struct list_head deleted_refs;
129130

130-
struct xarray name_cache;
131+
struct radix_tree_root name_cache;
131132
struct list_head name_cache_list;
132133
int name_cache_size;
133134

@@ -268,13 +269,14 @@ struct orphan_dir_info {
268269
struct name_cache_entry {
269270
struct list_head list;
270271
/*
271-
* On 32bit kernels, xarray has only 32bit indices, but we need to
272-
* handle 64bit inums. We use the lower 32bit of the 64bit inum to store
273-
* it in the tree. If more than one inum would fall into the same entry,
274-
* we use inum_aliases to store the additional entries. inum_aliases is
275-
* also used to store entries with the same inum but different generations.
272+
* radix_tree has only 32bit entries but we need to handle 64bit inums.
273+
* We use the lower 32bit of the 64bit inum to store it in the tree. If
274+
* more then one inum would fall into the same entry, we use radix_list
275+
* to store the additional entries. radix_list is also used to store
276+
* entries where two entries have the same inum but different
277+
* generations.
276278
*/
277-
struct list_head inum_aliases;
279+
struct list_head radix_list;
278280
u64 ino;
279281
u64 gen;
280282
u64 parent_ino;
@@ -2024,9 +2026,9 @@ static int did_overwrite_first_ref(struct send_ctx *sctx, u64 ino, u64 gen)
20242026
}
20252027

20262028
/*
2027-
* Insert a name cache entry. On 32bit kernels the xarray index is 32bit,
2029+
* Insert a name cache entry. On 32bit kernels the radix tree index is 32bit,
20282030
* so we need to do some special handling in case we have clashes. This function
2029-
* takes care of this with the help of name_cache_entry::inum_aliases.
2031+
* takes care of this with the help of name_cache_entry::radix_list.
20302032
* In case of error, nce is kfreed.
20312033
*/
20322034
static int name_cache_insert(struct send_ctx *sctx,
@@ -2035,7 +2037,8 @@ static int name_cache_insert(struct send_ctx *sctx,
20352037
int ret = 0;
20362038
struct list_head *nce_head;
20372039

2038-
nce_head = xa_load(&sctx->name_cache, (unsigned long)nce->ino);
2040+
nce_head = radix_tree_lookup(&sctx->name_cache,
2041+
(unsigned long)nce->ino);
20392042
if (!nce_head) {
20402043
nce_head = kmalloc(sizeof(*nce_head), GFP_KERNEL);
20412044
if (!nce_head) {
@@ -2044,14 +2047,14 @@ static int name_cache_insert(struct send_ctx *sctx,
20442047
}
20452048
INIT_LIST_HEAD(nce_head);
20462049

2047-
ret = xa_insert(&sctx->name_cache, nce->ino, nce_head, GFP_KERNEL);
2050+
ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head);
20482051
if (ret < 0) {
20492052
kfree(nce_head);
20502053
kfree(nce);
20512054
return ret;
20522055
}
20532056
}
2054-
list_add_tail(&nce->inum_aliases, nce_head);
2057+
list_add_tail(&nce->radix_list, nce_head);
20552058
list_add_tail(&nce->list, &sctx->name_cache_list);
20562059
sctx->name_cache_size++;
20572060

@@ -2063,22 +2066,23 @@ static void name_cache_delete(struct send_ctx *sctx,
20632066
{
20642067
struct list_head *nce_head;
20652068

2066-
nce_head = xa_load(&sctx->name_cache, (unsigned long)nce->ino);
2069+
nce_head = radix_tree_lookup(&sctx->name_cache,
2070+
(unsigned long)nce->ino);
20672071
if (!nce_head) {
20682072
btrfs_err(sctx->send_root->fs_info,
20692073
"name_cache_delete lookup failed ino %llu cache size %d, leaking memory",
20702074
nce->ino, sctx->name_cache_size);
20712075
}
20722076

2073-
list_del(&nce->inum_aliases);
2077+
list_del(&nce->radix_list);
20742078
list_del(&nce->list);
20752079
sctx->name_cache_size--;
20762080

20772081
/*
20782082
* We may not get to the final release of nce_head if the lookup fails
20792083
*/
20802084
if (nce_head && list_empty(nce_head)) {
2081-
xa_erase(&sctx->name_cache, (unsigned long)nce->ino);
2085+
radix_tree_delete(&sctx->name_cache, (unsigned long)nce->ino);
20822086
kfree(nce_head);
20832087
}
20842088
}
@@ -2089,11 +2093,11 @@ static struct name_cache_entry *name_cache_search(struct send_ctx *sctx,
20892093
struct list_head *nce_head;
20902094
struct name_cache_entry *cur;
20912095

2092-
nce_head = xa_load(&sctx->name_cache, (unsigned long)ino);
2096+
nce_head = radix_tree_lookup(&sctx->name_cache, (unsigned long)ino);
20932097
if (!nce_head)
20942098
return NULL;
20952099

2096-
list_for_each_entry(cur, nce_head, inum_aliases) {
2100+
list_for_each_entry(cur, nce_head, radix_list) {
20972101
if (cur->ino == ino && cur->gen == gen)
20982102
return cur;
20992103
}
@@ -7518,7 +7522,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg)
75187522

75197523
INIT_LIST_HEAD(&sctx->new_refs);
75207524
INIT_LIST_HEAD(&sctx->deleted_refs);
7521-
xa_init_flags(&sctx->name_cache, GFP_KERNEL);
7525+
INIT_RADIX_TREE(&sctx->name_cache, GFP_KERNEL);
75227526
INIT_LIST_HEAD(&sctx->name_cache_list);
75237527

75247528
sctx->flags = arg->flags;

0 commit comments

Comments
 (0)