Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcachefs: improve journal entry read fsck error messages

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>

+55 -41
+55 -41
fs/bcachefs/journal_io.c
··· 17 17 #include "sb-clean.h" 18 18 #include "trace.h" 19 19 20 + void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c, 21 + struct journal_replay *j) 22 + { 23 + darray_for_each(j->ptrs, i) { 24 + struct bch_dev *ca = bch_dev_bkey_exists(c, i->dev); 25 + u64 offset; 26 + 27 + div64_u64_rem(i->sector, ca->mi.bucket_size, &offset); 28 + 29 + if (i != j->ptrs.data) 30 + prt_printf(out, " "); 31 + prt_printf(out, "%u:%u:%u (sector %llu)", 32 + i->dev, i->bucket, i->bucket_offset, i->sector); 33 + } 34 + } 35 + 36 + static void bch2_journal_replay_to_text(struct printbuf *out, struct bch_fs *c, 37 + struct journal_replay *j) 38 + { 39 + prt_printf(out, "seq %llu ", le64_to_cpu(j->j.seq)); 40 + 41 + bch2_journal_ptrs_to_text(out, c, j); 42 + } 43 + 20 44 static struct nonce journal_nonce(const struct jset *jset) 21 45 { 22 46 return (struct nonce) {{ ··· 110 86 struct journal_replay **_i, *i, *dup; 111 87 size_t bytes = vstruct_bytes(j); 112 88 u64 last_seq = !JSET_NO_FLUSH(j) ? le64_to_cpu(j->last_seq) : 0; 89 + struct printbuf buf = PRINTBUF; 113 90 int ret = JOURNAL_ENTRY_ADD_OK; 114 91 115 92 /* Is this entry older than the range we need? */ ··· 155 130 */ 156 131 dup = *_i; 157 132 if (dup) { 158 - if (bytes == vstruct_bytes(&dup->j) && 159 - !memcmp(j, &dup->j, bytes)) { 160 - i = dup; 161 - goto found; 162 - } 133 + bool identical = bytes == vstruct_bytes(&dup->j) && 134 + !memcmp(j, &dup->j, bytes); 135 + bool not_identical = !identical && 136 + entry_ptr.csum_good && 137 + dup->csum_good; 163 138 164 - if (!entry_ptr.csum_good) { 165 - i = dup; 166 - goto found; 167 - } 139 + bool same_device = false; 140 + darray_for_each(dup->ptrs, ptr) 141 + if (ptr->dev == ca->dev_idx) 142 + same_device = true; 168 143 169 - if (!dup->csum_good) 144 + ret = darray_push(&dup->ptrs, entry_ptr); 145 + if (ret) 146 + goto out; 147 + 148 + bch2_journal_replay_to_text(&buf, c, dup); 149 + 150 + fsck_err_on(same_device, 151 + c, journal_entry_dup_same_device, 152 + "duplicate journal entry on same device\n %s", 153 + buf.buf); 154 + 155 + fsck_err_on(not_identical, 156 + c, journal_entry_replicas_data_mismatch, 157 + "found duplicate but non identical journal entries\n %s", 158 + buf.buf); 159 + 160 + if (entry_ptr.csum_good && !identical) 170 161 goto replace; 171 162 172 - fsck_err(c, journal_entry_replicas_data_mismatch, 173 - "found duplicate but non identical journal entries (seq %llu)", 174 - le64_to_cpu(j->seq)); 175 - i = dup; 176 - goto found; 163 + goto out; 177 164 } 178 165 replace: 179 166 i = kvpmalloc(offsetof(struct journal_replay, j) + bytes, GFP_KERNEL); ··· 196 159 i->csum_good = entry_ptr.csum_good; 197 160 i->ignore = false; 198 161 unsafe_memcpy(&i->j, j, bytes, "embedded variable length struct"); 199 - darray_push(&i->ptrs, entry_ptr); 200 162 201 163 if (dup) { 202 164 /* The first ptr should represent the jset we kept: */ 203 165 darray_for_each(dup->ptrs, ptr) 204 166 darray_push(&i->ptrs, *ptr); 205 167 __journal_replay_free(c, dup); 168 + } else { 169 + darray_push(&i->ptrs, entry_ptr); 206 170 } 207 171 208 172 *_i = i; 209 - found: 210 - darray_for_each(i->ptrs, ptr) 211 - if (ptr->dev == ca->dev_idx) { 212 - bch_err(c, "duplicate journal entry %llu on same device", 213 - le64_to_cpu(i->j.seq)); 214 - goto out; 215 - } 216 - 217 - ret = darray_push(&i->ptrs, entry_ptr); 218 173 out: 219 174 fsck_err: 175 + printbuf_exit(&buf); 220 176 return ret; 221 177 } 222 178 ··· 1165 1135 jlist->ret = ret; 1166 1136 mutex_unlock(&jlist->lock); 1167 1137 goto out; 1168 - } 1169 - 1170 - void bch2_journal_ptrs_to_text(struct printbuf *out, struct bch_fs *c, 1171 - struct journal_replay *j) 1172 - { 1173 - darray_for_each(j->ptrs, i) { 1174 - struct bch_dev *ca = bch_dev_bkey_exists(c, i->dev); 1175 - u64 offset; 1176 - 1177 - div64_u64_rem(i->sector, ca->mi.bucket_size, &offset); 1178 - 1179 - if (i != j->ptrs.data) 1180 - prt_printf(out, " "); 1181 - prt_printf(out, "%u:%u:%u (sector %llu)", 1182 - i->dev, i->bucket, i->bucket_offset, i->sector); 1183 - } 1184 1138 } 1185 1139 1186 1140 int bch2_journal_read(struct bch_fs *c,