brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 013a968 Raw
177 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include "bcachefs.h"4#include "sb-errors.h"5#include "super-io.h"6 7const char * const bch2_sb_error_strs[] = {8#define x(t, n, ...) [n] = #t,9	BCH_SB_ERRS()10#undef x11};12 13void bch2_sb_error_id_to_text(struct printbuf *out, enum bch_sb_error_id id)14{15	if (id < BCH_FSCK_ERR_MAX)16		prt_str(out, bch2_sb_error_strs[id]);17	else18		prt_printf(out, "(unknown error %u)", id);19}20 21static inline unsigned bch2_sb_field_errors_nr_entries(struct bch_sb_field_errors *e)22{23	return bch2_sb_field_nr_entries(e);24}25 26static inline unsigned bch2_sb_field_errors_u64s(unsigned nr)27{28	return (sizeof(struct bch_sb_field_errors) +29		sizeof(struct bch_sb_field_error_entry) * nr) / sizeof(u64);30}31 32static int bch2_sb_errors_validate(struct bch_sb *sb, struct bch_sb_field *f,33				   enum bch_validate_flags flags, struct printbuf *err)34{35	struct bch_sb_field_errors *e = field_to_type(f, errors);36	unsigned i, nr = bch2_sb_field_errors_nr_entries(e);37 38	for (i = 0; i < nr; i++) {39		if (!BCH_SB_ERROR_ENTRY_NR(&e->entries[i])) {40			prt_printf(err, "entry with count 0 (id ");41			bch2_sb_error_id_to_text(err, BCH_SB_ERROR_ENTRY_ID(&e->entries[i]));42			prt_printf(err, ")");43			return -BCH_ERR_invalid_sb_errors;44		}45 46		if (i + 1 < nr &&47		    BCH_SB_ERROR_ENTRY_ID(&e->entries[i]) >=48		    BCH_SB_ERROR_ENTRY_ID(&e->entries[i + 1])) {49			prt_printf(err, "entries out of order");50			return -BCH_ERR_invalid_sb_errors;51		}52	}53 54	return 0;55}56 57static void bch2_sb_errors_to_text(struct printbuf *out, struct bch_sb *sb,58				   struct bch_sb_field *f)59{60	struct bch_sb_field_errors *e = field_to_type(f, errors);61	unsigned i, nr = bch2_sb_field_errors_nr_entries(e);62 63	if (out->nr_tabstops <= 1)64		printbuf_tabstop_push(out, 16);65 66	for (i = 0; i < nr; i++) {67		bch2_sb_error_id_to_text(out, BCH_SB_ERROR_ENTRY_ID(&e->entries[i]));68		prt_tab(out);69		prt_u64(out, BCH_SB_ERROR_ENTRY_NR(&e->entries[i]));70		prt_tab(out);71		bch2_prt_datetime(out, le64_to_cpu(e->entries[i].last_error_time));72		prt_newline(out);73	}74}75 76const struct bch_sb_field_ops bch_sb_field_ops_errors = {77	.validate	= bch2_sb_errors_validate,78	.to_text	= bch2_sb_errors_to_text,79};80 81void bch2_sb_error_count(struct bch_fs *c, enum bch_sb_error_id err)82{83	bch_sb_errors_cpu *e = &c->fsck_error_counts;84	struct bch_sb_error_entry_cpu n = {85		.id = err,86		.nr = 1,87		.last_error_time = ktime_get_real_seconds()88	};89	unsigned i;90 91	mutex_lock(&c->fsck_error_counts_lock);92	for (i = 0; i < e->nr; i++) {93		if (err == e->data[i].id) {94			e->data[i].nr++;95			e->data[i].last_error_time = n.last_error_time;96			goto out;97		}98		if (err < e->data[i].id)99			break;100	}101 102	if (darray_make_room(e, 1))103		goto out;104 105	darray_insert_item(e, i, n);106out:107	mutex_unlock(&c->fsck_error_counts_lock);108}109 110void bch2_sb_errors_from_cpu(struct bch_fs *c)111{112	bch_sb_errors_cpu *src = &c->fsck_error_counts;113	struct bch_sb_field_errors *dst;114	unsigned i;115 116	mutex_lock(&c->fsck_error_counts_lock);117 118	dst = bch2_sb_field_resize(&c->disk_sb, errors,119				   bch2_sb_field_errors_u64s(src->nr));120 121	if (!dst)122		goto err;123 124	for (i = 0; i < src->nr; i++) {125		SET_BCH_SB_ERROR_ENTRY_ID(&dst->entries[i], src->data[i].id);126		SET_BCH_SB_ERROR_ENTRY_NR(&dst->entries[i], src->data[i].nr);127		dst->entries[i].last_error_time = cpu_to_le64(src->data[i].last_error_time);128	}129 130err:131	mutex_unlock(&c->fsck_error_counts_lock);132}133 134static int bch2_sb_errors_to_cpu(struct bch_fs *c)135{136	struct bch_sb_field_errors *src = bch2_sb_field_get(c->disk_sb.sb, errors);137	bch_sb_errors_cpu *dst = &c->fsck_error_counts;138	unsigned i, nr = bch2_sb_field_errors_nr_entries(src);139	int ret;140 141	if (!nr)142		return 0;143 144	mutex_lock(&c->fsck_error_counts_lock);145	ret = darray_make_room(dst, nr);146	if (ret)147		goto err;148 149	dst->nr = nr;150 151	for (i = 0; i < nr; i++) {152		dst->data[i].id = BCH_SB_ERROR_ENTRY_ID(&src->entries[i]);153		dst->data[i].nr = BCH_SB_ERROR_ENTRY_NR(&src->entries[i]);154		dst->data[i].last_error_time = le64_to_cpu(src->entries[i].last_error_time);155	}156err:157	mutex_unlock(&c->fsck_error_counts_lock);158 159	return ret;160}161 162void bch2_fs_sb_errors_exit(struct bch_fs *c)163{164	darray_exit(&c->fsck_error_counts);165}166 167void bch2_fs_sb_errors_init_early(struct bch_fs *c)168{169	mutex_init(&c->fsck_error_counts_lock);170	darray_init(&c->fsck_error_counts);171}172 173int bch2_fs_sb_errors_init(struct bch_fs *c)174{175	return bch2_sb_errors_to_cpu(c);176}177