~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/bcachefs/sb-errors.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 
  3 #include "bcachefs.h"
  4 #include "sb-errors.h"
  5 #include "super-io.h"
  6 
  7 const char * const bch2_sb_error_strs[] = {
  8 #define x(t, n, ...) [n] = #t,
  9         BCH_SB_ERRS()
 10         NULL
 11 };
 12 
 13 static void bch2_sb_error_id_to_text(struct printbuf *out, enum bch_sb_error_id id)
 14 {
 15         if (id < BCH_SB_ERR_MAX)
 16                 prt_str(out, bch2_sb_error_strs[id]);
 17         else
 18                 prt_printf(out, "(unknown error %u)", id);
 19 }
 20 
 21 static 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 
 26 static 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 
 32 static 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 
 57 static 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 
 76 const 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 
 81 void 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);
106 out:
107         mutex_unlock(&c->fsck_error_counts_lock);
108 }
109 
110 void 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 
130 err:
131         mutex_unlock(&c->fsck_error_counts_lock);
132 }
133 
134 static 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         }
156 err:
157         mutex_unlock(&c->fsck_error_counts_lock);
158 
159         return ret;
160 }
161 
162 void bch2_fs_sb_errors_exit(struct bch_fs *c)
163 {
164         darray_exit(&c->fsck_error_counts);
165 }
166 
167 void 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 
173 int bch2_fs_sb_errors_init(struct bch_fs *c)
174 {
175         return bch2_sb_errors_to_cpu(c);
176 }
177 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php