mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Update bcachefs sources to 76f72a0cc7 bcachefs: Improve error message in fsck
This commit is contained in:
parent
2bd18f4bae
commit
517440cc98
@ -1 +1 @@
|
|||||||
fd637ebda030609b15a473f01f1ef54bbe818f27
|
76f72a0cc7392f83567b3f477496d6efe8a98f6b
|
||||||
|
@ -521,6 +521,18 @@ struct journal_seq_blacklist_table {
|
|||||||
} entries[0];
|
} entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct journal_keys {
|
||||||
|
struct journal_key {
|
||||||
|
enum btree_id btree_id:8;
|
||||||
|
unsigned level:8;
|
||||||
|
struct bkey_i *k;
|
||||||
|
u32 journal_seq;
|
||||||
|
u32 journal_offset;
|
||||||
|
} *d;
|
||||||
|
size_t nr;
|
||||||
|
u64 journal_seq_base;
|
||||||
|
};
|
||||||
|
|
||||||
struct bch_fs {
|
struct bch_fs {
|
||||||
struct closure cl;
|
struct closure cl;
|
||||||
|
|
||||||
@ -787,6 +799,8 @@ struct bch_fs {
|
|||||||
mempool_t btree_bounce_pool;
|
mempool_t btree_bounce_pool;
|
||||||
|
|
||||||
struct journal journal;
|
struct journal journal;
|
||||||
|
struct list_head journal_entries;
|
||||||
|
struct journal_keys journal_keys;
|
||||||
|
|
||||||
u64 last_bucket_seq_cleanup;
|
u64 last_bucket_seq_cleanup;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
#include "bcachefs.h"
|
#include "bcachefs.h"
|
||||||
|
#include "bkey_on_stack.h"
|
||||||
#include "btree_update.h"
|
#include "btree_update.h"
|
||||||
#include "dirent.h"
|
#include "dirent.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@ -469,10 +470,12 @@ static int check_extents(struct bch_fs *c)
|
|||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter *iter;
|
struct btree_iter *iter;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
struct bkey prev = KEY(0, 0, 0);
|
struct bkey_on_stack prev;
|
||||||
u64 i_sectors;
|
u64 i_sectors;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
bkey_on_stack_init(&prev);
|
||||||
|
prev.k->k = KEY(0, 0, 0);
|
||||||
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
|
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
|
||||||
|
|
||||||
bch_verbose(c, "checking extents");
|
bch_verbose(c, "checking extents");
|
||||||
@ -482,24 +485,24 @@ static int check_extents(struct bch_fs *c)
|
|||||||
BTREE_ITER_INTENT);
|
BTREE_ITER_INTENT);
|
||||||
retry:
|
retry:
|
||||||
for_each_btree_key_continue(iter, 0, k, ret) {
|
for_each_btree_key_continue(iter, 0, k, ret) {
|
||||||
if (bkey_cmp(prev.p, bkey_start_pos(k.k)) > 0) {
|
if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) {
|
||||||
char buf1[100];
|
char buf1[200];
|
||||||
char buf2[100];
|
char buf2[200];
|
||||||
|
|
||||||
bch2_bkey_to_text(&PBUF(buf1), &prev);
|
bch2_bkey_val_to_text(&PBUF(buf1), c, bkey_i_to_s_c(prev.k));
|
||||||
bch2_bkey_to_text(&PBUF(buf2), k.k);
|
bch2_bkey_val_to_text(&PBUF(buf2), c, k);
|
||||||
|
|
||||||
if (fsck_err(c, "overlapping extents: %s, %s", buf1, buf2)) {
|
if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2)) {
|
||||||
ret = __bch2_trans_do(&trans, NULL, NULL,
|
ret = __bch2_trans_do(&trans, NULL, NULL,
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|
|
||||||
BTREE_INSERT_LAZY_RW,
|
BTREE_INSERT_LAZY_RW,
|
||||||
bch2_fix_overlapping_extent(&trans,
|
bch2_fix_overlapping_extent(&trans,
|
||||||
iter, k, prev.p));
|
iter, k, prev.k->k.p));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev = *k.k;
|
bkey_on_stack_reassemble(&prev, c, k);
|
||||||
|
|
||||||
ret = walk_inode(&trans, &w, k.k->p.inode);
|
ret = walk_inode(&trans, &w, k.k->p.inode);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -525,7 +528,8 @@ retry:
|
|||||||
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
|
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
|
||||||
w.inode.bi_sectors !=
|
w.inode.bi_sectors !=
|
||||||
(i_sectors = bch2_count_inode_sectors(&trans, w.cur_inum)),
|
(i_sectors = bch2_count_inode_sectors(&trans, w.cur_inum)),
|
||||||
c, "i_sectors wrong: got %llu, should be %llu",
|
c, "inode %llu has incorrect i_sectors: got %llu, should be %llu",
|
||||||
|
w.inode.bi_inum,
|
||||||
w.inode.bi_sectors, i_sectors)) {
|
w.inode.bi_sectors, i_sectors)) {
|
||||||
struct bkey_inode_buf p;
|
struct bkey_inode_buf p;
|
||||||
|
|
||||||
@ -567,6 +571,7 @@ err:
|
|||||||
fsck_err:
|
fsck_err:
|
||||||
if (ret == -EINTR)
|
if (ret == -EINTR)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
bkey_on_stack_exit(&prev, c);
|
||||||
return bch2_trans_exit(&trans) ?: ret;
|
return bch2_trans_exit(&trans) ?: ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +255,11 @@ enum opt_type {
|
|||||||
OPT_BOOL(), \
|
OPT_BOOL(), \
|
||||||
NO_SB_OPT, false, \
|
NO_SB_OPT, false, \
|
||||||
NULL, "Don't replay the journal") \
|
NULL, "Don't replay the journal") \
|
||||||
|
x(keep_journal, u8, \
|
||||||
|
OPT_MOUNT, \
|
||||||
|
OPT_BOOL(), \
|
||||||
|
NO_SB_OPT, false, \
|
||||||
|
NULL, "Don't free journal entries/keys after startup")\
|
||||||
x(noexcl, u8, \
|
x(noexcl, u8, \
|
||||||
OPT_MOUNT, \
|
OPT_MOUNT, \
|
||||||
OPT_BOOL(), \
|
OPT_BOOL(), \
|
||||||
|
@ -198,7 +198,7 @@ void bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *i
|
|||||||
|
|
||||||
/* sort and dedup all keys in the journal: */
|
/* sort and dedup all keys in the journal: */
|
||||||
|
|
||||||
static void journal_entries_free(struct list_head *list)
|
void bch2_journal_entries_free(struct list_head *list)
|
||||||
{
|
{
|
||||||
|
|
||||||
while (!list_empty(list)) {
|
while (!list_empty(list)) {
|
||||||
@ -236,7 +236,7 @@ static int journal_sort_seq_cmp(const void *_l, const void *_r)
|
|||||||
bkey_cmp(l->k->k.p, r->k->k.p);
|
bkey_cmp(l->k->k.p, r->k->k.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void journal_keys_free(struct journal_keys *keys)
|
void bch2_journal_keys_free(struct journal_keys *keys)
|
||||||
{
|
{
|
||||||
kvfree(keys->d);
|
kvfree(keys->d);
|
||||||
keys->d = NULL;
|
keys->d = NULL;
|
||||||
@ -801,8 +801,6 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
const char *err = "cannot allocate memory";
|
const char *err = "cannot allocate memory";
|
||||||
struct bch_sb_field_clean *clean = NULL;
|
struct bch_sb_field_clean *clean = NULL;
|
||||||
u64 journal_seq;
|
u64 journal_seq;
|
||||||
LIST_HEAD(journal_entries);
|
|
||||||
struct journal_keys journal_keys = { NULL };
|
|
||||||
bool wrote = false, write_sb = false;
|
bool wrote = false, write_sb = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -824,30 +822,30 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
if (!c->sb.clean || c->opts.fsck) {
|
if (!c->sb.clean || c->opts.fsck) {
|
||||||
struct jset *j;
|
struct jset *j;
|
||||||
|
|
||||||
ret = bch2_journal_read(c, &journal_entries);
|
ret = bch2_journal_read(c, &c->journal_entries);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (mustfix_fsck_err_on(c->sb.clean && !journal_empty(&journal_entries), c,
|
if (mustfix_fsck_err_on(c->sb.clean && !journal_empty(&c->journal_entries), c,
|
||||||
"filesystem marked clean but journal not empty")) {
|
"filesystem marked clean but journal not empty")) {
|
||||||
c->sb.compat &= ~(1ULL << BCH_COMPAT_FEAT_ALLOC_INFO);
|
c->sb.compat &= ~(1ULL << BCH_COMPAT_FEAT_ALLOC_INFO);
|
||||||
SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
|
SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
|
||||||
c->sb.clean = false;
|
c->sb.clean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->sb.clean && list_empty(&journal_entries)) {
|
if (!c->sb.clean && list_empty(&c->journal_entries)) {
|
||||||
bch_err(c, "no journal entries found");
|
bch_err(c, "no journal entries found");
|
||||||
ret = BCH_FSCK_REPAIR_IMPOSSIBLE;
|
ret = BCH_FSCK_REPAIR_IMPOSSIBLE;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
journal_keys = journal_keys_sort(&journal_entries);
|
c->journal_keys = journal_keys_sort(&c->journal_entries);
|
||||||
if (!journal_keys.d) {
|
if (!c->journal_keys.d) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
j = &list_last_entry(&journal_entries,
|
j = &list_last_entry(&c->journal_entries,
|
||||||
struct journal_replay, list)->j;
|
struct journal_replay, list)->j;
|
||||||
|
|
||||||
ret = verify_superblock_clean(c, &clean, j);
|
ret = verify_superblock_clean(c, &clean, j);
|
||||||
@ -866,7 +864,7 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = journal_replay_early(c, clean, &journal_entries);
|
ret = journal_replay_early(c, clean, &c->journal_entries);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -884,15 +882,15 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
|
|
||||||
ret = bch2_blacklist_table_initialize(c);
|
ret = bch2_blacklist_table_initialize(c);
|
||||||
|
|
||||||
if (!list_empty(&journal_entries)) {
|
if (!list_empty(&c->journal_entries)) {
|
||||||
ret = verify_journal_entries_not_blacklisted_or_missing(c,
|
ret = verify_journal_entries_not_blacklisted_or_missing(c,
|
||||||
&journal_entries);
|
&c->journal_entries);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bch2_fs_journal_start(&c->journal, journal_seq,
|
ret = bch2_fs_journal_start(&c->journal, journal_seq,
|
||||||
&journal_entries);
|
&c->journal_entries);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -902,14 +900,14 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
|
|
||||||
bch_verbose(c, "starting alloc read");
|
bch_verbose(c, "starting alloc read");
|
||||||
err = "error reading allocation information";
|
err = "error reading allocation information";
|
||||||
ret = bch2_alloc_read(c, &journal_keys);
|
ret = bch2_alloc_read(c, &c->journal_keys);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
bch_verbose(c, "alloc read done");
|
bch_verbose(c, "alloc read done");
|
||||||
|
|
||||||
bch_verbose(c, "starting stripes_read");
|
bch_verbose(c, "starting stripes_read");
|
||||||
err = "error reading stripes";
|
err = "error reading stripes";
|
||||||
ret = bch2_stripes_read(c, &journal_keys);
|
ret = bch2_stripes_read(c, &c->journal_keys);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
bch_verbose(c, "stripes_read done");
|
bch_verbose(c, "stripes_read done");
|
||||||
@ -925,7 +923,7 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
*/
|
*/
|
||||||
bch_info(c, "starting metadata mark and sweep");
|
bch_info(c, "starting metadata mark and sweep");
|
||||||
err = "error in mark and sweep";
|
err = "error in mark and sweep";
|
||||||
ret = bch2_gc(c, &journal_keys, true, true);
|
ret = bch2_gc(c, &c->journal_keys, true, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
bch_verbose(c, "mark and sweep done");
|
bch_verbose(c, "mark and sweep done");
|
||||||
@ -936,7 +934,7 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags)) {
|
test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags)) {
|
||||||
bch_info(c, "starting mark and sweep");
|
bch_info(c, "starting mark and sweep");
|
||||||
err = "error in mark and sweep";
|
err = "error in mark and sweep";
|
||||||
ret = bch2_gc(c, &journal_keys, true, false);
|
ret = bch2_gc(c, &c->journal_keys, true, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
bch_verbose(c, "mark and sweep done");
|
bch_verbose(c, "mark and sweep done");
|
||||||
@ -957,7 +955,7 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
|
|
||||||
bch_verbose(c, "starting journal replay");
|
bch_verbose(c, "starting journal replay");
|
||||||
err = "journal replay failed";
|
err = "journal replay failed";
|
||||||
ret = bch2_journal_replay(c, journal_keys);
|
ret = bch2_journal_replay(c, c->journal_keys);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
bch_verbose(c, "journal replay done");
|
bch_verbose(c, "journal replay done");
|
||||||
@ -1053,8 +1051,10 @@ fsck_err:
|
|||||||
set_bit(BCH_FS_FSCK_DONE, &c->flags);
|
set_bit(BCH_FS_FSCK_DONE, &c->flags);
|
||||||
bch2_flush_fsck_errs(c);
|
bch2_flush_fsck_errs(c);
|
||||||
|
|
||||||
journal_keys_free(&journal_keys);
|
if (!c->opts.keep_journal) {
|
||||||
journal_entries_free(&journal_entries);
|
bch2_journal_keys_free(&c->journal_keys);
|
||||||
|
bch2_journal_entries_free(&c->journal_entries);
|
||||||
|
}
|
||||||
kfree(clean);
|
kfree(clean);
|
||||||
if (ret)
|
if (ret)
|
||||||
bch_err(c, "Error in recovery: %s (%i)", err, ret);
|
bch_err(c, "Error in recovery: %s (%i)", err, ret);
|
||||||
|
@ -2,18 +2,6 @@
|
|||||||
#ifndef _BCACHEFS_RECOVERY_H
|
#ifndef _BCACHEFS_RECOVERY_H
|
||||||
#define _BCACHEFS_RECOVERY_H
|
#define _BCACHEFS_RECOVERY_H
|
||||||
|
|
||||||
struct journal_keys {
|
|
||||||
struct journal_key {
|
|
||||||
enum btree_id btree_id:8;
|
|
||||||
unsigned level:8;
|
|
||||||
struct bkey_i *k;
|
|
||||||
u32 journal_seq;
|
|
||||||
u32 journal_offset;
|
|
||||||
} *d;
|
|
||||||
size_t nr;
|
|
||||||
u64 journal_seq_base;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define for_each_journal_key(keys, i) \
|
#define for_each_journal_key(keys, i) \
|
||||||
for (i = (keys).d; i < (keys).d + (keys).nr; (i)++)
|
for (i = (keys).d; i < (keys).d + (keys).nr; (i)++)
|
||||||
|
|
||||||
@ -56,6 +44,9 @@ void bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,
|
|||||||
struct journal_keys *,
|
struct journal_keys *,
|
||||||
struct btree *);
|
struct btree *);
|
||||||
|
|
||||||
|
void bch2_journal_keys_free(struct journal_keys *);
|
||||||
|
void bch2_journal_entries_free(struct list_head *);
|
||||||
|
|
||||||
int bch2_fs_recovery(struct bch_fs *);
|
int bch2_fs_recovery(struct bch_fs *);
|
||||||
int bch2_fs_initialize(struct bch_fs *);
|
int bch2_fs_initialize(struct bch_fs *);
|
||||||
|
|
||||||
|
@ -500,6 +500,8 @@ static void bch2_fs_free(struct bch_fs *c)
|
|||||||
bch2_io_clock_exit(&c->io_clock[WRITE]);
|
bch2_io_clock_exit(&c->io_clock[WRITE]);
|
||||||
bch2_io_clock_exit(&c->io_clock[READ]);
|
bch2_io_clock_exit(&c->io_clock[READ]);
|
||||||
bch2_fs_compress_exit(c);
|
bch2_fs_compress_exit(c);
|
||||||
|
bch2_journal_keys_free(&c->journal_keys);
|
||||||
|
bch2_journal_entries_free(&c->journal_entries);
|
||||||
percpu_free_rwsem(&c->mark_lock);
|
percpu_free_rwsem(&c->mark_lock);
|
||||||
kfree(c->usage_scratch);
|
kfree(c->usage_scratch);
|
||||||
free_percpu(c->usage[1]);
|
free_percpu(c->usage[1]);
|
||||||
@ -689,6 +691,8 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
|
|||||||
INIT_WORK(&c->journal_seq_blacklist_gc_work,
|
INIT_WORK(&c->journal_seq_blacklist_gc_work,
|
||||||
bch2_blacklist_entries_gc);
|
bch2_blacklist_entries_gc);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&c->journal_entries);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&c->fsck_errors);
|
INIT_LIST_HEAD(&c->fsck_errors);
|
||||||
mutex_init(&c->fsck_error_lock);
|
mutex_init(&c->fsck_error_lock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user