mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
bcachefs: use a radix tree for inum bitmap in fsck
The change to use the cpu nr for the high bits of new inode numbers means that inode numbers are very space - we see -ENOMEM during fsck without this. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
a3e7226268
commit
fe4584765d
1 changed files with 13 additions and 26 deletions
|
@ -866,36 +866,22 @@ static int check_lostfound(struct bch_fs *c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct inode_bitmap {
|
||||
unsigned long *bits;
|
||||
size_t size;
|
||||
};
|
||||
typedef GENRADIX(unsigned long) inode_bitmap;
|
||||
|
||||
static inline bool inode_bitmap_test(struct inode_bitmap *b, size_t nr)
|
||||
static inline bool inode_bitmap_test(inode_bitmap *b, size_t nr)
|
||||
{
|
||||
return nr < b->size ? test_bit(nr, b->bits) : false;
|
||||
unsigned long *w = genradix_ptr(b, nr / BITS_PER_LONG);
|
||||
return w ? test_bit(nr & (BITS_PER_LONG - 1), w) : false;
|
||||
}
|
||||
|
||||
static inline int inode_bitmap_set(struct inode_bitmap *b, size_t nr)
|
||||
static inline int inode_bitmap_set(inode_bitmap *b, size_t nr)
|
||||
{
|
||||
if (nr >= b->size) {
|
||||
size_t new_size = max_t(size_t, max_t(size_t,
|
||||
PAGE_SIZE * 8,
|
||||
b->size * 2),
|
||||
nr + 1);
|
||||
void *n;
|
||||
unsigned long *w = genradix_ptr_alloc(b, nr / BITS_PER_LONG, GFP_KERNEL);
|
||||
|
||||
new_size = roundup_pow_of_two(new_size);
|
||||
n = krealloc(b->bits, new_size / 8, GFP_KERNEL|__GFP_ZERO);
|
||||
if (!n) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!w)
|
||||
return -ENOMEM;
|
||||
|
||||
b->bits = n;
|
||||
b->size = new_size;
|
||||
}
|
||||
|
||||
__set_bit(nr, b->bits);
|
||||
*w |= 1UL << (nr & (BITS_PER_LONG - 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -934,7 +920,7 @@ noinline_for_stack
|
|||
static int check_directory_structure(struct bch_fs *c,
|
||||
struct bch_inode_unpacked *lostfound_inode)
|
||||
{
|
||||
struct inode_bitmap dirs_done = { NULL, 0 };
|
||||
inode_bitmap dirs_done;
|
||||
struct pathbuf path = { 0, 0, NULL };
|
||||
struct pathbuf_entry *e;
|
||||
struct btree_trans trans;
|
||||
|
@ -951,6 +937,7 @@ static int check_directory_structure(struct bch_fs *c,
|
|||
|
||||
/* DFS: */
|
||||
restart_dfs:
|
||||
genradix_init(&dirs_done);
|
||||
had_unreachable = false;
|
||||
|
||||
ret = inode_bitmap_set(&dirs_done, BCACHEFS_ROOT_INO);
|
||||
|
@ -1057,7 +1044,7 @@ static int check_directory_structure(struct bch_fs *c,
|
|||
|
||||
if (had_unreachable) {
|
||||
bch_info(c, "reattached unreachable directories, restarting pass to check for loops");
|
||||
kfree(dirs_done.bits);
|
||||
genradix_free(&dirs_done);
|
||||
kfree(path.entries);
|
||||
memset(&dirs_done, 0, sizeof(dirs_done));
|
||||
memset(&path, 0, sizeof(path));
|
||||
|
@ -1066,7 +1053,7 @@ static int check_directory_structure(struct bch_fs *c,
|
|||
err:
|
||||
fsck_err:
|
||||
ret = bch2_trans_exit(&trans) ?: ret;
|
||||
kfree(dirs_done.bits);
|
||||
genradix_free(&dirs_done);
|
||||
kfree(path.entries);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue