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

bcachefs: KEY_TYPE_alloc_v2

This introduces a new version of KEY_TYPE_alloc, which uses the new
varint encoding introduced for inodes. This means we'll eventually be
able to support much larger bucket sizes (for SMR devices), and the
read/write time fields are expanded to 64 bits - which will be used in
the next patch to get rid of the periodic rescaling of those fields.

Also, for buckets that are members of erasure coded stripes, this adds
persistent fields for the index of the stripe they're members of and the
stripe redundancy. This is part of work to get rid of having to scan and
read into memory the alloc and stripes btrees at mount time.

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

authored by

Kent Overstreet and committed by
Kent Overstreet
7f4e1d5d 26452d1d

+407 -303
+171 -84
fs/bcachefs/alloc_background.c
··· 15 15 #include "error.h" 16 16 #include "recovery.h" 17 17 #include "trace.h" 18 + #include "varint.h" 18 19 19 20 #include <linux/kthread.h> 20 21 #include <linux/math64.h> ··· 25 24 #include <linux/sched/task.h> 26 25 #include <linux/sort.h> 27 26 28 - static const char * const bch2_alloc_field_names[] = { 29 - #define x(name, bytes) #name, 30 - BCH_ALLOC_FIELDS() 27 + static const unsigned BCH_ALLOC_V1_FIELD_BYTES[] = { 28 + #define x(name, bits) [BCH_ALLOC_FIELD_V1_##name] = bits / 8, 29 + BCH_ALLOC_FIELDS_V1() 31 30 #undef x 32 - NULL 33 31 }; 34 32 35 33 static void bch2_recalc_oldest_io(struct bch_fs *, struct bch_dev *, int); ··· 67 67 68 68 /* Persistent alloc info: */ 69 69 70 - static inline u64 get_alloc_field(const struct bch_alloc *a, 71 - const void **p, unsigned field) 70 + static inline u64 alloc_field_v1_get(const struct bch_alloc *a, 71 + const void **p, unsigned field) 72 72 { 73 - unsigned bytes = BCH_ALLOC_FIELD_BYTES[field]; 73 + unsigned bytes = BCH_ALLOC_V1_FIELD_BYTES[field]; 74 74 u64 v; 75 75 76 76 if (!(a->fields & (1 << field))) ··· 97 97 return v; 98 98 } 99 99 100 - static inline void put_alloc_field(struct bkey_i_alloc *a, void **p, 101 - unsigned field, u64 v) 100 + static inline void alloc_field_v1_put(struct bkey_i_alloc *a, void **p, 101 + unsigned field, u64 v) 102 102 { 103 - unsigned bytes = BCH_ALLOC_FIELD_BYTES[field]; 103 + unsigned bytes = BCH_ALLOC_V1_FIELD_BYTES[field]; 104 104 105 105 if (!v) 106 106 return; ··· 127 127 *p += bytes; 128 128 } 129 129 130 + static void bch2_alloc_unpack_v1(struct bkey_alloc_unpacked *out, 131 + struct bkey_s_c k) 132 + { 133 + const struct bch_alloc *in = bkey_s_c_to_alloc(k).v; 134 + const void *d = in->data; 135 + unsigned idx = 0; 136 + 137 + out->gen = in->gen; 138 + 139 + #define x(_name, _bits) out->_name = alloc_field_v1_get(in, &d, idx++); 140 + BCH_ALLOC_FIELDS_V1() 141 + #undef x 142 + } 143 + 144 + static void bch2_alloc_pack_v1(struct bkey_alloc_buf *dst, 145 + const struct bkey_alloc_unpacked src) 146 + { 147 + struct bkey_i_alloc *a = bkey_alloc_init(&dst->k); 148 + void *d = a->v.data; 149 + unsigned bytes, idx = 0; 150 + 151 + a->k.p = POS(src.dev, src.bucket); 152 + a->v.fields = 0; 153 + a->v.gen = src.gen; 154 + 155 + #define x(_name, _bits) alloc_field_v1_put(a, &d, idx++, src._name); 156 + BCH_ALLOC_FIELDS_V1() 157 + #undef x 158 + bytes = (void *) d - (void *) &a->v; 159 + set_bkey_val_bytes(&a->k, bytes); 160 + memset_u64s_tail(&a->v, 0, bytes); 161 + } 162 + 163 + static int bch2_alloc_unpack_v2(struct bkey_alloc_unpacked *out, 164 + struct bkey_s_c k) 165 + { 166 + struct bkey_s_c_alloc_v2 a = bkey_s_c_to_alloc_v2(k); 167 + const u8 *in = a.v->data; 168 + const u8 *end = bkey_val_end(a); 169 + unsigned fieldnr = 0; 170 + int ret; 171 + u64 v; 172 + 173 + out->gen = a.v->gen; 174 + out->oldest_gen = a.v->oldest_gen; 175 + out->data_type = a.v->data_type; 176 + 177 + #define x(_name, _bits) \ 178 + if (fieldnr < a.v->nr_fields) { \ 179 + ret = bch2_varint_decode(in, end, &v); \ 180 + if (ret < 0) \ 181 + return ret; \ 182 + in += ret; \ 183 + } else { \ 184 + v = 0; \ 185 + } \ 186 + out->_name = v; \ 187 + if (v != out->_name) \ 188 + return -1; \ 189 + fieldnr++; 190 + 191 + BCH_ALLOC_FIELDS_V2() 192 + #undef x 193 + return 0; 194 + } 195 + 196 + static void bch2_alloc_pack_v2(struct bkey_alloc_buf *dst, 197 + const struct bkey_alloc_unpacked src) 198 + { 199 + struct bkey_i_alloc_v2 *a = bkey_alloc_v2_init(&dst->k); 200 + unsigned nr_fields = 0, last_nonzero_fieldnr = 0; 201 + u8 *out = a->v.data; 202 + u8 *end = (void *) &dst[1]; 203 + u8 *last_nonzero_field = out; 204 + unsigned bytes; 205 + 206 + a->k.p = POS(src.dev, src.bucket); 207 + a->v.gen = src.gen; 208 + a->v.oldest_gen = src.oldest_gen; 209 + a->v.data_type = src.data_type; 210 + 211 + #define x(_name, _bits) \ 212 + nr_fields++; \ 213 + \ 214 + if (src._name) { \ 215 + out += bch2_varint_encode(out, src._name); \ 216 + \ 217 + last_nonzero_field = out; \ 218 + last_nonzero_fieldnr = nr_fields; \ 219 + } else { \ 220 + *out++ = 0; \ 221 + } 222 + 223 + BCH_ALLOC_FIELDS_V2() 224 + #undef x 225 + BUG_ON(out > end); 226 + 227 + out = last_nonzero_field; 228 + a->v.nr_fields = last_nonzero_fieldnr; 229 + 230 + bytes = (u8 *) out - (u8 *) &a->v; 231 + set_bkey_val_bytes(&a->k, bytes); 232 + memset_u64s_tail(&a->v, 0, bytes); 233 + } 234 + 130 235 struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c k) 131 236 { 132 - struct bkey_alloc_unpacked ret = { .gen = 0 }; 237 + struct bkey_alloc_unpacked ret = { 238 + .dev = k.k->p.inode, 239 + .bucket = k.k->p.offset, 240 + .gen = 0, 241 + }; 133 242 134 - if (k.k->type == KEY_TYPE_alloc) { 135 - const struct bch_alloc *a = bkey_s_c_to_alloc(k).v; 136 - const void *d = a->data; 137 - unsigned idx = 0; 243 + if (k.k->type == KEY_TYPE_alloc_v2) 244 + bch2_alloc_unpack_v2(&ret, k); 245 + else if (k.k->type == KEY_TYPE_alloc) 246 + bch2_alloc_unpack_v1(&ret, k); 138 247 139 - ret.gen = a->gen; 140 - 141 - #define x(_name, _bits) ret._name = get_alloc_field(a, &d, idx++); 142 - BCH_ALLOC_FIELDS() 143 - #undef x 144 - } 145 248 return ret; 146 249 } 147 250 148 - void bch2_alloc_pack(struct bkey_i_alloc *dst, 251 + void bch2_alloc_pack(struct bch_fs *c, 252 + struct bkey_alloc_buf *dst, 149 253 const struct bkey_alloc_unpacked src) 150 254 { 151 - unsigned idx = 0; 152 - void *d = dst->v.data; 153 - unsigned bytes; 154 - 155 - dst->v.fields = 0; 156 - dst->v.gen = src.gen; 157 - 158 - #define x(_name, _bits) put_alloc_field(dst, &d, idx++, src._name); 159 - BCH_ALLOC_FIELDS() 160 - #undef x 161 - 162 - bytes = (void *) d - (void *) &dst->v; 163 - set_bkey_val_bytes(&dst->k, bytes); 164 - memset_u64s_tail(&dst->v, 0, bytes); 255 + if (c->sb.features & (1ULL << BCH_FEATURE_alloc_v2)) 256 + bch2_alloc_pack_v2(dst, src); 257 + else 258 + bch2_alloc_pack_v1(dst, src); 165 259 } 166 260 167 261 static unsigned bch_alloc_val_u64s(const struct bch_alloc *a) 168 262 { 169 263 unsigned i, bytes = offsetof(struct bch_alloc, data); 170 264 171 - for (i = 0; i < ARRAY_SIZE(BCH_ALLOC_FIELD_BYTES); i++) 265 + for (i = 0; i < ARRAY_SIZE(BCH_ALLOC_V1_FIELD_BYTES); i++) 172 266 if (a->fields & (1 << i)) 173 - bytes += BCH_ALLOC_FIELD_BYTES[i]; 267 + bytes += BCH_ALLOC_V1_FIELD_BYTES[i]; 174 268 175 269 return DIV_ROUND_UP(bytes, sizeof(u64)); 176 270 } 177 271 178 - const char *bch2_alloc_invalid(const struct bch_fs *c, struct bkey_s_c k) 272 + const char *bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k) 179 273 { 180 274 struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k); 181 275 ··· 284 190 return NULL; 285 191 } 286 192 287 - void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, 288 - struct bkey_s_c k) 193 + const char *bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k) 289 194 { 290 - struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k); 291 - const void *d = a.v->data; 292 - unsigned i; 195 + struct bkey_alloc_unpacked u; 293 196 294 - pr_buf(out, "gen %u", a.v->gen); 197 + if (k.k->p.inode >= c->sb.nr_devices || 198 + !c->devs[k.k->p.inode]) 199 + return "invalid device"; 295 200 296 - for (i = 0; i < BCH_ALLOC_FIELD_NR; i++) 297 - if (a.v->fields & (1 << i)) 298 - pr_buf(out, " %s %llu", 299 - bch2_alloc_field_names[i], 300 - get_alloc_field(a.v, &d, i)); 201 + if (bch2_alloc_unpack_v2(&u, k)) 202 + return "unpack error"; 203 + 204 + return NULL; 205 + } 206 + 207 + void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, 208 + struct bkey_s_c k) 209 + { 210 + struct bkey_alloc_unpacked u = bch2_alloc_unpack(k); 211 + 212 + pr_buf(out, "gen %u oldest_gen %u data_type %u", 213 + u.gen, u.oldest_gen, u.data_type); 214 + #define x(_name, ...) pr_buf(out, #_name " %llu ", (u64) u._name); 215 + BCH_ALLOC_FIELDS_V2() 216 + #undef x 301 217 } 302 218 303 219 static int bch2_alloc_read_fn(struct bch_fs *c, enum btree_id id, ··· 317 213 struct bucket *g; 318 214 struct bkey_alloc_unpacked u; 319 215 320 - if (level || k.k->type != KEY_TYPE_alloc) 216 + if (level || 217 + (k.k->type != KEY_TYPE_alloc && 218 + k.k->type != KEY_TYPE_alloc_v2)) 321 219 return 0; 322 220 323 221 ca = bch_dev_bkey_exists(c, k.k->p.inode); ··· 387 281 struct bucket *g; 388 282 struct bucket_mark m; 389 283 struct bkey_alloc_unpacked old_u, new_u; 390 - __BKEY_PADDED(k, 8) alloc_key; /* hack: */ 391 - struct bkey_i_alloc *a; 284 + struct bkey_alloc_buf a; 392 285 int ret; 393 286 retry: 394 287 bch2_trans_begin(trans); ··· 408 303 ca = bch_dev_bkey_exists(c, iter->pos.inode); 409 304 g = bucket(ca, iter->pos.offset); 410 305 m = READ_ONCE(g->mark); 411 - new_u = alloc_mem_to_key(g, m); 306 + new_u = alloc_mem_to_key(iter, g, m); 412 307 percpu_up_read(&c->mark_lock); 413 308 414 309 if (!bkey_alloc_unpacked_cmp(old_u, new_u)) 415 310 return 0; 416 311 417 - a = bkey_alloc_init(&alloc_key.k); 418 - a->k.p = iter->pos; 419 - bch2_alloc_pack(a, new_u); 420 - 421 - bch2_trans_update(trans, iter, &a->k_i, 312 + bch2_alloc_pack(c, &a, new_u); 313 + bch2_trans_update(trans, iter, &a.k, 422 314 BTREE_TRIGGER_NORUN); 423 315 ret = bch2_trans_commit(trans, NULL, NULL, 424 316 BTREE_INSERT_NOFAIL|flags); ··· 575 473 struct bch_dev *ca = bch_dev_bkey_exists(c, dev); 576 474 struct btree_iter *iter; 577 475 struct bucket *g; 578 - struct bkey_i_alloc *a; 476 + struct bkey_alloc_buf *a; 579 477 struct bkey_alloc_unpacked u; 580 - u16 *time; 478 + u64 *time; 581 479 int ret = 0; 582 480 583 481 iter = bch2_trans_get_iter(trans, BTREE_ID_ALLOC, POS(dev, bucket_nr), ··· 588 486 if (ret) 589 487 goto out; 590 488 591 - a = bch2_trans_kmalloc(trans, BKEY_ALLOC_U64s_MAX * 8); 489 + a = bch2_trans_kmalloc(trans, sizeof(struct bkey_alloc_buf)); 592 490 ret = PTR_ERR_OR_ZERO(a); 593 491 if (ret) 594 492 goto out; 595 493 596 494 percpu_down_read(&c->mark_lock); 597 495 g = bucket(ca, bucket_nr); 598 - u = alloc_mem_to_key(g, READ_ONCE(g->mark)); 496 + u = alloc_mem_to_key(iter, g, READ_ONCE(g->mark)); 599 497 percpu_up_read(&c->mark_lock); 600 - 601 - bkey_alloc_init(&a->k_i); 602 - a->k.p = iter->pos; 603 498 604 499 time = rw == READ ? &u.read_time : &u.write_time; 605 500 if (*time == c->bucket_clock[rw].hand) ··· 604 505 605 506 *time = c->bucket_clock[rw].hand; 606 507 607 - bch2_alloc_pack(a, u); 608 - 609 - ret = bch2_trans_update(trans, iter, &a->k_i, 0) ?: 508 + bch2_alloc_pack(c, a, u); 509 + ret = bch2_trans_update(trans, iter, &a->k, 0) ?: 610 510 bch2_trans_commit(trans, NULL, NULL, 0); 611 511 out: 612 512 bch2_trans_iter_put(trans, iter); ··· 961 863 struct btree_iter *iter, 962 864 u64 *journal_seq, unsigned flags) 963 865 { 964 - #if 0 965 - __BKEY_PADDED(k, BKEY_ALLOC_VAL_U64s_MAX) alloc_key; 966 - #else 967 - /* hack: */ 968 - __BKEY_PADDED(k, 8) alloc_key; 969 - #endif 970 866 struct bch_fs *c = trans->c; 971 - struct bkey_i_alloc *a; 867 + struct bkey_alloc_buf a; 972 868 struct bkey_alloc_unpacked u; 973 869 struct bucket *g; 974 870 struct bucket_mark m; ··· 1012 920 goto out; 1013 921 } 1014 922 1015 - BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8); 1016 - 1017 923 bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b)); 1018 924 retry: 1019 925 ret = bch2_btree_iter_traverse(iter); ··· 1021 931 percpu_down_read(&c->mark_lock); 1022 932 g = bucket(ca, iter->pos.offset); 1023 933 m = READ_ONCE(g->mark); 1024 - u = alloc_mem_to_key(g, m); 934 + u = alloc_mem_to_key(iter, g, m); 1025 935 1026 936 percpu_up_read(&c->mark_lock); 1027 937 ··· 1034 944 u.read_time = c->bucket_clock[READ].hand; 1035 945 u.write_time = c->bucket_clock[WRITE].hand; 1036 946 1037 - a = bkey_alloc_init(&alloc_key.k); 1038 - a->k.p = iter->pos; 1039 - bch2_alloc_pack(a, u); 1040 - 1041 - bch2_trans_update(trans, iter, &a->k_i, 947 + bch2_alloc_pack(c, &a, u); 948 + bch2_trans_update(trans, iter, &a.k, 1042 949 BTREE_TRIGGER_BUCKET_INVALIDATE); 1043 950 1044 951 /*
+40 -8
fs/bcachefs/alloc_background.h
··· 7 7 #include "debug.h" 8 8 9 9 struct bkey_alloc_unpacked { 10 + u64 bucket; 11 + u8 dev; 10 12 u8 gen; 13 + u8 oldest_gen; 14 + u8 data_type; 11 15 #define x(_name, _bits) u##_bits _name; 12 - BCH_ALLOC_FIELDS() 16 + BCH_ALLOC_FIELDS_V2() 13 17 #undef x 14 18 }; 19 + 20 + struct bkey_alloc_buf { 21 + struct bkey_i k; 22 + 23 + union { 24 + struct { 25 + #define x(_name, _bits) + _bits / 8 26 + u8 _pad[8 + BCH_ALLOC_FIELDS_V1()]; 27 + #undef x 28 + } _v1; 29 + struct { 30 + #define x(_name, _bits) + 8 + _bits / 8 31 + u8 _pad[8 + BCH_ALLOC_FIELDS_V2()]; 32 + #undef x 33 + } _v2; 34 + }; 35 + } __attribute__((packed, aligned(8))); 15 36 16 37 /* How out of date a pointer gen is allowed to be: */ 17 38 #define BUCKET_GC_GEN_MAX 96U ··· 41 20 static inline bool bkey_alloc_unpacked_cmp(struct bkey_alloc_unpacked l, 42 21 struct bkey_alloc_unpacked r) 43 22 { 44 - return l.gen != r.gen 45 - #define x(_name, _bits) || l._name != r._name 46 - BCH_ALLOC_FIELDS() 23 + return l.gen != r.gen || 24 + l.oldest_gen != r.oldest_gen || 25 + l.data_type != r.data_type 26 + #define x(_name, ...) || l._name != r._name 27 + BCH_ALLOC_FIELDS_V2() 47 28 #undef x 48 29 ; 49 30 } 50 31 51 32 struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c); 52 - void bch2_alloc_pack(struct bkey_i_alloc *, 33 + void bch2_alloc_pack(struct bch_fs *, struct bkey_alloc_buf *, 53 34 const struct bkey_alloc_unpacked); 54 35 55 36 int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int); 56 37 57 38 static inline struct bkey_alloc_unpacked 58 - alloc_mem_to_key(struct bucket *g, struct bucket_mark m) 39 + alloc_mem_to_key(struct btree_iter *iter, 40 + struct bucket *g, struct bucket_mark m) 59 41 { 60 42 return (struct bkey_alloc_unpacked) { 43 + .dev = iter->pos.inode, 44 + .bucket = iter->pos.offset, 61 45 .gen = m.gen, 62 46 .oldest_gen = g->oldest_gen, 63 47 .data_type = m.data_type, ··· 75 49 76 50 #define ALLOC_SCAN_BATCH(ca) max_t(size_t, 1, (ca)->mi.nbuckets >> 9) 77 51 78 - const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c); 52 + const char *bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c); 53 + const char *bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c); 79 54 void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); 80 55 81 56 #define bch2_bkey_ops_alloc (struct bkey_ops) { \ 82 - .key_invalid = bch2_alloc_invalid, \ 57 + .key_invalid = bch2_alloc_v1_invalid, \ 58 + .val_to_text = bch2_alloc_to_text, \ 59 + } 60 + 61 + #define bch2_bkey_ops_alloc_v2 (struct bkey_ops) { \ 62 + .key_invalid = bch2_alloc_v2_invalid, \ 83 63 .val_to_text = bch2_alloc_to_text, \ 84 64 } 85 65
+33 -23
fs/bcachefs/bcachefs_format.h
··· 345 345 x(reflink_v, 16) \ 346 346 x(inline_data, 17) \ 347 347 x(btree_ptr_v2, 18) \ 348 - x(indirect_inline_data, 19) 348 + x(indirect_inline_data, 19) \ 349 + x(alloc_v2, 20) 349 350 350 351 enum bch_bkey_type { 351 352 #define x(name, nr) KEY_TYPE_##name = nr, ··· 556 555 #if defined(__LITTLE_ENDIAN_BITFIELD) 557 556 __u64 type:5, 558 557 block:8, 559 - idx:51; 558 + redundancy:4, 559 + idx:47; 560 560 #elif defined (__BIG_ENDIAN_BITFIELD) 561 - __u64 idx:51, 561 + __u64 idx:47, 562 + redundancy:4, 562 563 block:8, 563 564 type:5; 564 565 #endif ··· 806 803 __u8 data[]; 807 804 } __attribute__((packed, aligned(8))); 808 805 809 - #define BCH_ALLOC_FIELDS() \ 806 + #define BCH_ALLOC_FIELDS_V1() \ 810 807 x(read_time, 16) \ 811 808 x(write_time, 16) \ 812 809 x(data_type, 8) \ 813 810 x(dirty_sectors, 16) \ 814 811 x(cached_sectors, 16) \ 815 - x(oldest_gen, 8) 812 + x(oldest_gen, 8) \ 813 + x(stripe, 32) \ 814 + x(stripe_redundancy, 8) 815 + 816 + struct bch_alloc_v2 { 817 + struct bch_val v; 818 + __u8 nr_fields; 819 + __u8 gen; 820 + __u8 oldest_gen; 821 + __u8 data_type; 822 + __u8 data[]; 823 + } __attribute__((packed, aligned(8))); 824 + 825 + #define BCH_ALLOC_FIELDS_V2() \ 826 + x(read_time, 64) \ 827 + x(write_time, 64) \ 828 + x(dirty_sectors, 16) \ 829 + x(cached_sectors, 16) \ 830 + x(stripe, 32) \ 831 + x(stripe_redundancy, 8) 816 832 817 833 enum { 818 - #define x(name, bytes) BCH_ALLOC_FIELD_##name, 819 - BCH_ALLOC_FIELDS() 834 + #define x(name, _bits) BCH_ALLOC_FIELD_V1_##name, 835 + BCH_ALLOC_FIELDS_V1() 820 836 #undef x 821 837 BCH_ALLOC_FIELD_NR 822 838 }; 823 - 824 - static const unsigned BCH_ALLOC_FIELD_BYTES[] = { 825 - #define x(name, bits) [BCH_ALLOC_FIELD_##name] = bits / 8, 826 - BCH_ALLOC_FIELDS() 827 - #undef x 828 - }; 829 - 830 - #define x(name, bits) + (bits / 8) 831 - static const unsigned BKEY_ALLOC_VAL_U64s_MAX = 832 - DIV_ROUND_UP(offsetof(struct bch_alloc, data) 833 - BCH_ALLOC_FIELDS(), sizeof(u64)); 834 - #undef x 835 - 836 - #define BKEY_ALLOC_U64s_MAX (BKEY_U64s + BKEY_ALLOC_VAL_U64s_MAX) 837 839 838 840 /* Quotas: */ 839 841 ··· 1345 1337 x(btree_updates_journalled, 13) \ 1346 1338 x(reflink_inline_data, 14) \ 1347 1339 x(new_varint, 15) \ 1348 - x(journal_no_flush, 16) 1340 + x(journal_no_flush, 16) \ 1341 + x(alloc_v2, 17) 1349 1342 1350 1343 #define BCH_SB_FEATURES_ALL \ 1351 1344 ((1ULL << BCH_FEATURE_new_siphash)| \ ··· 1354 1345 (1ULL << BCH_FEATURE_btree_ptr_v2)| \ 1355 1346 (1ULL << BCH_FEATURE_extents_above_btree_updates)|\ 1356 1347 (1ULL << BCH_FEATURE_new_varint)| \ 1357 - (1ULL << BCH_FEATURE_journal_no_flush)) 1348 + (1ULL << BCH_FEATURE_journal_no_flush)| \ 1349 + (1ULL << BCH_FEATURE_alloc_v2)) 1358 1350 1359 1351 enum bch_sb_feature { 1360 1352 #define x(f, n) BCH_FEATURE_##f,
+1
fs/bcachefs/bkey.h
··· 538 538 BKEY_VAL_ACCESSORS(inline_data); 539 539 BKEY_VAL_ACCESSORS(btree_ptr_v2); 540 540 BKEY_VAL_ACCESSORS(indirect_inline_data); 541 + BKEY_VAL_ACCESSORS(alloc_v2); 541 542 542 543 /* byte order helpers */ 543 544
+127 -153
fs/bcachefs/buckets.c
··· 688 688 struct bucket_mark old_m, m; 689 689 690 690 /* We don't do anything for deletions - do we?: */ 691 - if (new.k->type != KEY_TYPE_alloc) 691 + if (new.k->type != KEY_TYPE_alloc && 692 + new.k->type != KEY_TYPE_alloc_v2) 692 693 return 0; 693 694 694 695 /* ··· 712 711 m.data_type = u.data_type; 713 712 m.dirty_sectors = u.dirty_sectors; 714 713 m.cached_sectors = u.cached_sectors; 714 + m.stripe = u.stripe != 0; 715 715 716 716 if (journal_seq) { 717 717 m.journal_seq_valid = 1; ··· 726 724 g->io_time[WRITE] = u.write_time; 727 725 g->oldest_gen = u.oldest_gen; 728 726 g->gen_valid = 1; 727 + g->stripe = u.stripe; 728 + g->stripe_redundancy = u.stripe_redundancy; 729 729 730 730 /* 731 731 * need to know if we're getting called from the invalidate path or ··· 922 918 return 0; 923 919 } 924 920 925 - static int bucket_set_stripe(struct bch_fs *c, struct bkey_s_c k, 921 + static int mark_stripe_bucket(struct bch_fs *c, struct bkey_s_c k, 926 922 unsigned ptr_idx, 927 923 struct bch_fs_usage *fs_usage, 928 - u64 journal_seq, unsigned flags, 929 - bool enabled) 924 + u64 journal_seq, unsigned flags) 930 925 { 931 926 const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; 932 927 unsigned nr_data = s->nr_blocks - s->nr_redundant; ··· 938 935 char buf[200]; 939 936 int ret; 940 937 941 - if (enabled) 942 - g->ec_redundancy = s->nr_redundant; 938 + if (g->stripe && g->stripe != k.k->p.offset) { 939 + bch2_fs_inconsistent(c, 940 + "bucket %u:%zu gen %u: multiple stripes using same bucket\n%s", 941 + ptr->dev, PTR_BUCKET_NR(ca, ptr), new.gen, 942 + (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)); 943 + return -EINVAL; 944 + } 943 945 944 946 old = bucket_cmpxchg(g, new, ({ 945 947 ret = check_bucket_ref(c, k, ptr, 0, 0, new.gen, new.data_type, ··· 952 944 if (ret) 953 945 return ret; 954 946 955 - if (new.stripe && enabled) 956 - bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, 957 - "bucket %u:%zu gen %u: multiple stripes using same bucket\n%s", 958 - ptr->dev, PTR_BUCKET_NR(ca, ptr), new.gen, 959 - (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)); 960 - 961 - if (!new.stripe && !enabled) 962 - bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, 963 - "bucket %u:%zu gen %u: deleting stripe but not marked\n%s", 964 - ptr->dev, PTR_BUCKET_NR(ca, ptr), new.gen, 965 - (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)); 966 - 967 - new.stripe = enabled; 968 - 969 - if ((flags & BTREE_TRIGGER_GC) && parity) { 970 - new.data_type = enabled ? BCH_DATA_parity : 0; 971 - new.dirty_sectors = enabled ? le16_to_cpu(s->sectors): 0; 947 + if (parity) { 948 + new.data_type = BCH_DATA_parity; 949 + new.dirty_sectors = le16_to_cpu(s->sectors); 972 950 } 973 951 974 952 if (journal_seq) { ··· 963 969 } 964 970 })); 965 971 966 - if (!enabled) 967 - g->ec_redundancy = 0; 972 + g->stripe = k.k->p.offset; 973 + g->stripe_redundancy = s->nr_redundant; 968 974 969 975 bch2_dev_usage_update(c, ca, fs_usage, old, new, gc); 970 976 return 0; ··· 1160 1166 unsigned i; 1161 1167 int ret; 1162 1168 1169 + BUG_ON(gc && old_s); 1170 + 1163 1171 if (!m || (old_s && !m->alive)) { 1164 1172 bch_err_ratelimited(c, "error marking nonexistent stripe %zu", 1165 1173 idx); ··· 1169 1173 } 1170 1174 1171 1175 if (!new_s) { 1172 - /* Deleting: */ 1173 - for (i = 0; i < old_s->nr_blocks; i++) { 1174 - ret = bucket_set_stripe(c, old, i, fs_usage, 1175 - journal_seq, flags, false); 1176 - if (ret) 1177 - return ret; 1178 - } 1179 - 1180 - if (!gc && m->on_heap) { 1181 - spin_lock(&c->ec_stripes_heap_lock); 1182 - bch2_stripes_heap_del(c, m, idx); 1183 - spin_unlock(&c->ec_stripes_heap_lock); 1184 - } 1185 - 1186 - if (gc) 1187 - update_replicas(c, fs_usage, &m->r.e, 1188 - -((s64) m->sectors * m->nr_redundant)); 1176 + spin_lock(&c->ec_stripes_heap_lock); 1177 + bch2_stripes_heap_del(c, m, idx); 1178 + spin_unlock(&c->ec_stripes_heap_lock); 1189 1179 1190 1180 memset(m, 0, sizeof(*m)); 1191 1181 } else { 1192 - BUG_ON(old_s && new_s->nr_blocks != old_s->nr_blocks); 1193 - BUG_ON(old_s && new_s->nr_redundant != old_s->nr_redundant); 1194 - 1195 - for (i = 0; i < new_s->nr_blocks; i++) { 1196 - if (!old_s || 1197 - memcmp(new_s->ptrs + i, 1198 - old_s->ptrs + i, 1199 - sizeof(struct bch_extent_ptr))) { 1200 - 1201 - if (old_s) { 1202 - bucket_set_stripe(c, old, i, fs_usage, 1203 - journal_seq, flags, false); 1204 - if (ret) 1205 - return ret; 1206 - } 1207 - ret = bucket_set_stripe(c, new, i, fs_usage, 1208 - journal_seq, flags, true); 1209 - if (ret) 1210 - return ret; 1211 - } 1212 - } 1213 - 1214 1182 m->alive = true; 1215 1183 m->sectors = le16_to_cpu(new_s->sectors); 1216 1184 m->algorithm = new_s->algorithm; ··· 1183 1223 m->blocks_nonempty = 0; 1184 1224 1185 1225 for (i = 0; i < new_s->nr_blocks; i++) { 1186 - unsigned s = stripe_blockcount_get(new_s, i); 1187 - 1188 - /* 1189 - * gc recalculates this field from stripe ptr 1190 - * references: 1191 - */ 1192 - if (!gc) 1193 - m->block_sectors[i] = s; 1194 - m->blocks_nonempty += !!s; 1226 + m->block_sectors[i] = 1227 + stripe_blockcount_get(new_s, i); 1228 + m->blocks_nonempty += !!m->block_sectors[i]; 1195 1229 } 1196 1230 1197 - if (gc && old_s) 1198 - update_replicas(c, fs_usage, &m->r.e, 1199 - -((s64) m->sectors * m->nr_redundant)); 1200 - 1201 1231 bch2_bkey_to_replicas(&m->r.e, new); 1202 - 1203 - if (gc) 1204 - update_replicas(c, fs_usage, &m->r.e, 1205 - ((s64) m->sectors * m->nr_redundant)); 1206 1232 1207 1233 if (!gc) { 1208 1234 spin_lock(&c->ec_stripes_heap_lock); 1209 1235 bch2_stripes_heap_update(c, m, idx); 1210 1236 spin_unlock(&c->ec_stripes_heap_lock); 1211 1237 } 1238 + } 1239 + 1240 + if (gc) { 1241 + /* 1242 + * gc recalculates this field from stripe ptr 1243 + * references: 1244 + */ 1245 + memset(m->block_sectors, 0, sizeof(m->block_sectors)); 1246 + m->blocks_nonempty = 0; 1247 + 1248 + for (i = 0; i < new_s->nr_blocks; i++) { 1249 + ret = mark_stripe_bucket(c, new, i, fs_usage, 1250 + journal_seq, flags); 1251 + if (ret) 1252 + return ret; 1253 + } 1254 + 1255 + update_replicas(c, fs_usage, &m->r.e, 1256 + ((s64) m->sectors * m->nr_redundant)); 1212 1257 } 1213 1258 1214 1259 return 0; ··· 1239 1274 1240 1275 switch (k.k->type) { 1241 1276 case KEY_TYPE_alloc: 1277 + case KEY_TYPE_alloc_v2: 1242 1278 ret = bch2_mark_alloc(c, old, new, fs_usage, journal_seq, flags); 1243 1279 break; 1244 1280 case KEY_TYPE_btree_ptr: ··· 1508 1542 return ret; 1509 1543 } 1510 1544 1511 - static int bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter **_iter, 1512 - const struct bch_extent_ptr *ptr, 1513 - struct bkey_alloc_unpacked *u) 1545 + static struct bkey_alloc_buf * 1546 + bch2_trans_start_alloc_update(struct btree_trans *trans, struct btree_iter **_iter, 1547 + const struct bch_extent_ptr *ptr, 1548 + struct bkey_alloc_unpacked *u) 1514 1549 { 1515 1550 struct bch_fs *c = trans->c; 1516 1551 struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); ··· 1519 1552 struct bucket *g; 1520 1553 struct btree_iter *iter; 1521 1554 struct bkey_s_c k; 1555 + struct bkey_alloc_buf *a; 1522 1556 int ret; 1557 + 1558 + a = bch2_trans_kmalloc(trans, sizeof(struct bkey_alloc_buf)); 1559 + if (IS_ERR(a)) 1560 + return a; 1523 1561 1524 1562 iter = trans_get_update(trans, BTREE_ID_ALLOC, pos, &k); 1525 1563 if (iter) { ··· 1537 1565 ret = bch2_btree_iter_traverse(iter); 1538 1566 if (ret) { 1539 1567 bch2_trans_iter_put(trans, iter); 1540 - return ret; 1568 + return ERR_PTR(ret); 1541 1569 } 1542 1570 1543 1571 percpu_down_read(&c->mark_lock); 1544 1572 g = bucket(ca, pos.offset); 1545 - *u = alloc_mem_to_key(g, READ_ONCE(g->mark)); 1573 + *u = alloc_mem_to_key(iter, g, READ_ONCE(g->mark)); 1546 1574 percpu_up_read(&c->mark_lock); 1547 1575 } 1548 1576 1549 1577 *_iter = iter; 1550 - return 0; 1578 + return a; 1551 1579 } 1552 1580 1553 1581 static int bch2_trans_mark_pointer(struct btree_trans *trans, ··· 1557 1585 struct bch_fs *c = trans->c; 1558 1586 struct btree_iter *iter; 1559 1587 struct bkey_alloc_unpacked u; 1560 - struct bkey_i_alloc *a; 1588 + struct bkey_alloc_buf *a; 1561 1589 int ret; 1562 1590 1563 - ret = bch2_trans_start_alloc_update(trans, &iter, &p.ptr, &u); 1564 - if (ret) 1565 - return ret; 1591 + a = bch2_trans_start_alloc_update(trans, &iter, &p.ptr, &u); 1592 + if (IS_ERR(a)) 1593 + return PTR_ERR(a); 1566 1594 1567 1595 ret = __mark_pointer(c, k, &p.ptr, sectors, data_type, u.gen, &u.data_type, 1568 1596 &u.dirty_sectors, &u.cached_sectors); 1569 1597 if (ret) 1570 1598 goto out; 1571 1599 1572 - a = bch2_trans_kmalloc(trans, BKEY_ALLOC_U64s_MAX * 8); 1573 - ret = PTR_ERR_OR_ZERO(a); 1574 - if (ret) 1575 - goto out; 1576 - 1577 - bkey_alloc_init(&a->k_i); 1578 - a->k.p = iter->pos; 1579 - bch2_alloc_pack(a, u); 1580 - bch2_trans_update(trans, iter, &a->k_i, 0); 1600 + bch2_alloc_pack(c, a, u); 1601 + bch2_trans_update(trans, iter, &a->k, 0); 1581 1602 out: 1582 1603 bch2_trans_iter_put(trans, iter); 1583 1604 return ret; ··· 1681 1716 } 1682 1717 1683 1718 static int bch2_trans_mark_stripe_alloc_ref(struct btree_trans *trans, 1684 - const struct bch_extent_ptr *ptr, 1685 - s64 sectors, bool parity) 1719 + struct bkey_s_c_stripe s, 1720 + unsigned idx, bool deleting) 1686 1721 { 1687 - struct bkey_i_alloc *a; 1722 + struct bch_fs *c = trans->c; 1723 + const struct bch_extent_ptr *ptr = &s.v->ptrs[idx]; 1724 + struct bkey_alloc_buf *a; 1688 1725 struct btree_iter *iter; 1689 1726 struct bkey_alloc_unpacked u; 1690 - int ret; 1727 + bool parity = idx >= s.v->nr_blocks - s.v->nr_redundant; 1728 + int ret = 0; 1691 1729 1692 - ret = bch2_trans_start_alloc_update(trans, &iter, ptr, &u); 1693 - if (ret) 1694 - return ret; 1730 + a = bch2_trans_start_alloc_update(trans, &iter, ptr, &u); 1731 + if (IS_ERR(a)) 1732 + return PTR_ERR(a); 1695 1733 1696 1734 if (parity) { 1735 + s64 sectors = le16_to_cpu(s.v->sectors); 1736 + 1737 + if (deleting) 1738 + sectors = -sectors; 1739 + 1697 1740 u.dirty_sectors += sectors; 1698 1741 u.data_type = u.dirty_sectors 1699 1742 ? BCH_DATA_parity 1700 1743 : 0; 1701 1744 } 1702 1745 1703 - a = bch2_trans_kmalloc(trans, BKEY_ALLOC_U64s_MAX * 8); 1704 - ret = PTR_ERR_OR_ZERO(a); 1705 - if (ret) 1706 - goto err; 1746 + if (!deleting) { 1747 + if (bch2_fs_inconsistent_on(u.stripe && u.stripe != s.k->p.offset, c, 1748 + "bucket %llu:%llu gen %u: multiple stripes using same bucket (%u, %llu)", 1749 + iter->pos.inode, iter->pos.offset, u.gen, 1750 + u.stripe, s.k->p.offset)) { 1751 + ret = -EIO; 1752 + goto err; 1753 + } 1707 1754 1708 - bkey_alloc_init(&a->k_i); 1709 - a->k.p = iter->pos; 1710 - bch2_alloc_pack(a, u); 1711 - bch2_trans_update(trans, iter, &a->k_i, 0); 1755 + u.stripe = s.k->p.offset; 1756 + u.stripe_redundancy = s.v->nr_redundant; 1757 + } else { 1758 + u.stripe = 0; 1759 + u.stripe_redundancy = 0; 1760 + } 1761 + 1762 + bch2_alloc_pack(c, a, u); 1763 + bch2_trans_update(trans, iter, &a->k, 0); 1712 1764 err: 1713 1765 bch2_trans_iter_put(trans, iter); 1714 1766 return ret; ··· 1735 1753 struct bkey_s_c old, struct bkey_s_c new, 1736 1754 unsigned flags) 1737 1755 { 1738 - const struct bch_stripe *old_s = old.k->type == KEY_TYPE_stripe 1739 - ? bkey_s_c_to_stripe(old).v : NULL; 1740 - const struct bch_stripe *new_s = new.k->type == KEY_TYPE_stripe 1741 - ? bkey_s_c_to_stripe(new).v : NULL; 1756 + struct bkey_s_c_stripe old_s = { NULL }; 1757 + struct bkey_s_c_stripe new_s = { NULL }; 1742 1758 struct bch_replicas_padded r; 1743 1759 unsigned i; 1744 1760 int ret = 0; 1745 1761 1762 + if (old.k->type == KEY_TYPE_stripe) 1763 + old_s = bkey_s_c_to_stripe(old); 1764 + if (new.k->type == KEY_TYPE_stripe) 1765 + new_s = bkey_s_c_to_stripe(new); 1766 + 1746 1767 /* 1747 1768 * If the pointers aren't changing, we don't need to do anything: 1748 1769 */ 1749 - if (new_s && old_s && 1750 - !memcmp(old_s->ptrs, new_s->ptrs, 1751 - new_s->nr_blocks * sizeof(struct bch_extent_ptr))) 1770 + if (new_s.k && old_s.k && 1771 + new_s.v->nr_blocks == old_s.v->nr_blocks && 1772 + new_s.v->nr_redundant == old_s.v->nr_redundant && 1773 + !memcmp(old_s.v->ptrs, new_s.v->ptrs, 1774 + new_s.v->nr_blocks * sizeof(struct bch_extent_ptr))) 1752 1775 return 0; 1753 1776 1754 - if (new_s) { 1755 - unsigned nr_data = new_s->nr_blocks - new_s->nr_redundant; 1756 - s64 sectors = le16_to_cpu(new_s->sectors); 1777 + if (new_s.k) { 1778 + s64 sectors = le16_to_cpu(new_s.v->sectors); 1757 1779 1758 1780 bch2_bkey_to_replicas(&r.e, new); 1759 - update_replicas_list(trans, &r.e, sectors * new_s->nr_redundant); 1781 + update_replicas_list(trans, &r.e, sectors * new_s.v->nr_redundant); 1760 1782 1761 - for (i = 0; i < new_s->nr_blocks; i++) { 1762 - bool parity = i >= nr_data; 1763 - 1764 - ret = bch2_trans_mark_stripe_alloc_ref(trans, 1765 - &new_s->ptrs[i], sectors, parity); 1783 + for (i = 0; i < new_s.v->nr_blocks; i++) { 1784 + ret = bch2_trans_mark_stripe_alloc_ref(trans, new_s, 1785 + i, false); 1766 1786 if (ret) 1767 1787 return ret; 1768 1788 } 1769 1789 } 1770 1790 1771 - if (old_s) { 1772 - unsigned nr_data = old_s->nr_blocks - old_s->nr_redundant; 1773 - s64 sectors = -((s64) le16_to_cpu(old_s->sectors)); 1791 + if (old_s.k) { 1792 + s64 sectors = -((s64) le16_to_cpu(old_s.v->sectors)); 1774 1793 1775 1794 bch2_bkey_to_replicas(&r.e, old); 1776 - update_replicas_list(trans, &r.e, sectors * old_s->nr_redundant); 1795 + update_replicas_list(trans, &r.e, sectors * old_s.v->nr_redundant); 1777 1796 1778 - for (i = 0; i < old_s->nr_blocks; i++) { 1779 - bool parity = i >= nr_data; 1780 - 1781 - ret = bch2_trans_mark_stripe_alloc_ref(trans, 1782 - &old_s->ptrs[i], sectors, parity); 1797 + for (i = 0; i < old_s.v->nr_blocks; i++) { 1798 + ret = bch2_trans_mark_stripe_alloc_ref(trans, old_s, 1799 + i, true); 1783 1800 if (ret) 1784 1801 return ret; 1785 1802 } ··· 2049 2068 struct bch_fs *c = trans->c; 2050 2069 struct btree_iter *iter; 2051 2070 struct bkey_alloc_unpacked u; 2052 - struct bkey_i_alloc *a; 2071 + struct bkey_alloc_buf *a; 2053 2072 struct bch_extent_ptr ptr = { 2054 2073 .dev = ca->dev_idx, 2055 2074 .offset = bucket_to_sector(ca, b), 2056 2075 }; 2057 2076 int ret = 0; 2058 2077 2059 - a = bch2_trans_kmalloc(trans, BKEY_ALLOC_U64s_MAX * 8); 2060 - ret = PTR_ERR_OR_ZERO(a); 2061 - if (ret) 2062 - return ret; 2063 - 2064 - ret = bch2_trans_start_alloc_update(trans, &iter, &ptr, &u); 2065 - if (ret) 2066 - return ret; 2078 + a = bch2_trans_start_alloc_update(trans, &iter, &ptr, &u); 2079 + if (IS_ERR(a)) 2080 + return PTR_ERR(a); 2067 2081 2068 2082 if (u.data_type && u.data_type != type) { 2069 2083 bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, ··· 2091 2115 u.data_type = type; 2092 2116 u.dirty_sectors = sectors; 2093 2117 2094 - bkey_alloc_init(&a->k_i); 2095 - a->k.p = iter->pos; 2096 - bch2_alloc_pack(a, u); 2097 - bch2_trans_update(trans, iter, &a->k_i, 0); 2118 + bch2_alloc_pack(c, a, u); 2119 + bch2_trans_update(trans, iter, &a->k, 0); 2098 2120 out: 2099 2121 bch2_trans_iter_put(trans, iter); 2100 2122 return ret;
+2 -1
fs/bcachefs/buckets_types.h
··· 41 41 u8 oldest_gen; 42 42 u8 gc_gen; 43 43 unsigned gen_valid:1; 44 - u8 ec_redundancy; 44 + u8 stripe_redundancy; 45 + u32 stripe; 45 46 }; 46 47 47 48 struct bucket_array {
+25 -10
fs/bcachefs/ec.c
··· 105 105 { 106 106 const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; 107 107 108 + if (!bkey_cmp(k.k->p, POS_MIN)) 109 + return "stripe at pos 0"; 110 + 108 111 if (k.k->p.inode) 109 112 return "invalid stripe key"; 110 113 ··· 282 279 struct bch_csum got = ec_block_checksum(buf, i, offset); 283 280 284 281 if (bch2_crc_cmp(want, got)) { 282 + char buf2[200]; 283 + 284 + bch2_bkey_val_to_text(&PBUF(buf2), c, bkey_i_to_s_c(&buf->key.k_i)); 285 + 285 286 bch_err_ratelimited(c, 286 - "stripe checksum error at %u:%u: csum type %u, expected %llx got %llx", 287 - i, j, v->csum_type, 288 - want.lo, got.lo); 287 + "stripe checksum error for %ps at %u:%u: csum type %u, expected %llx got %llx\n%s", 288 + (void *) _RET_IP_, i, j, v->csum_type, 289 + want.lo, got.lo, buf2); 289 290 clear_bit(i, buf->valid); 290 291 break; 291 292 } ··· 342 335 static void ec_block_endio(struct bio *bio) 343 336 { 344 337 struct ec_bio *ec_bio = container_of(bio, struct ec_bio, bio); 338 + struct bch_stripe *v = &ec_bio->buf->key.v; 339 + struct bch_extent_ptr *ptr = &v->ptrs[ec_bio->idx]; 345 340 struct bch_dev *ca = ec_bio->ca; 346 341 struct closure *cl = bio->bi_private; 347 342 ··· 351 342 bio_data_dir(bio) ? "write" : "read", 352 343 bch2_blk_status_to_str(bio->bi_status))) 353 344 clear_bit(ec_bio->idx, ec_bio->buf->valid); 345 + 346 + if (ptr_stale(ca, ptr)) { 347 + bch_err_ratelimited(ca->fs, 348 + "error %s stripe: stale pointer after io", 349 + bio_data_dir(bio) == READ ? "reading from" : "writing to"); 350 + clear_bit(ec_bio->idx, ec_bio->buf->valid); 351 + } 354 352 355 353 bio_put(&ec_bio->bio); 356 354 percpu_ref_put(&ca->io_ref); ··· 668 652 669 653 static int ec_stripe_delete(struct bch_fs *c, size_t idx) 670 654 { 671 - //pr_info("deleting stripe %zu", idx); 672 655 return bch2_btree_delete_range(c, BTREE_ID_EC, 673 656 POS(0, idx), 674 657 POS(0, idx + 1), ··· 810 795 *dst = (struct bch_extent_stripe_ptr) { 811 796 .type = 1 << BCH_EXTENT_ENTRY_stripe_ptr, 812 797 .block = block, 798 + .redundancy = s->key.v.nr_redundant, 813 799 .idx = s->key.k.p.offset, 814 800 }; 815 801 } ··· 1069 1053 1070 1054 if (!ob) 1071 1055 return; 1072 - 1073 - //pr_info("adding backpointer at %llu:%llu", pos.inode, pos.offset); 1074 1056 1075 1057 ec = ob->ec; 1076 1058 mutex_lock(&ec->lock); ··· 1362 1348 struct stripe *m; 1363 1349 size_t heap_idx; 1364 1350 u64 stripe_idx; 1351 + s64 ret = -1; 1365 1352 1366 1353 if (may_create_new_stripe(c)) 1367 1354 return -1; 1368 1355 1369 1356 spin_lock(&c->ec_stripes_heap_lock); 1370 1357 for (heap_idx = 0; heap_idx < h->used; heap_idx++) { 1358 + /* No blocks worth reusing, stripe will just be deleted: */ 1371 1359 if (!h->data[heap_idx].blocks_nonempty) 1372 1360 continue; 1373 1361 ··· 1381 1365 m->sectors == head->blocksize && 1382 1366 m->blocks_nonempty < m->nr_blocks - m->nr_redundant) { 1383 1367 bch2_stripes_heap_del(c, m, stripe_idx); 1384 - spin_unlock(&c->ec_stripes_heap_lock); 1385 - return stripe_idx; 1368 + ret = stripe_idx; 1369 + break; 1386 1370 } 1387 1371 } 1388 - 1389 1372 spin_unlock(&c->ec_stripes_heap_lock); 1390 - return -1; 1373 + return ret; 1391 1374 } 1392 1375 1393 1376 struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
+4 -17
fs/bcachefs/extents.c
··· 703 703 if (p.ptr.cached) 704 704 continue; 705 705 706 - if (p.has_ec) { 707 - struct stripe *s = 708 - genradix_ptr(&c->stripes[0], p.ec.idx); 709 - 710 - WARN_ON(!s); 711 - if (s) 712 - replicas += s->nr_redundant; 713 - } 706 + if (p.has_ec) 707 + replicas += p.ec.redundancy; 714 708 715 709 replicas++; 716 710 ··· 727 733 if (ca->mi.state != BCH_MEMBER_STATE_FAILED) 728 734 durability = max_t(unsigned, durability, ca->mi.durability); 729 735 730 - if (p.has_ec) { 731 - struct stripe *s = 732 - genradix_ptr(&c->stripes[0], p.ec.idx); 736 + if (p.has_ec) 737 + durability += p.ec.redundancy; 733 738 734 - if (WARN_ON(!s)) 735 - goto out; 736 - 737 - durability += s->nr_redundant; 738 - } 739 - out: 740 739 return durability; 741 740 } 742 741
+4 -7
fs/bcachefs/movinggc.c
··· 92 92 data_opts->btree_insert_flags = BTREE_INSERT_USE_RESERVE; 93 93 data_opts->rewrite_dev = p.ptr.dev; 94 94 95 - if (p.has_ec) { 96 - struct stripe *m = genradix_ptr(&c->stripes[0], p.ec.idx); 97 - 98 - data_opts->nr_replicas += m->nr_redundant; 99 - } 95 + if (p.has_ec) 96 + data_opts->nr_replicas += p.ec.redundancy; 100 97 101 98 return DATA_REWRITE; 102 99 } ··· 176 179 bucket_sectors_used(m) >= ca->mi.bucket_size) 177 180 continue; 178 181 179 - WARN_ON(m.stripe && !g->ec_redundancy); 182 + WARN_ON(m.stripe && !g->stripe_redundancy); 180 183 181 184 e = (struct copygc_heap_entry) { 182 185 .dev = dev_idx, 183 186 .gen = m.gen, 184 - .replicas = 1 + g->ec_redundancy, 187 + .replicas = 1 + g->stripe_redundancy, 185 188 .fragmentation = bucket_sectors_used(m) * (1U << 15) 186 189 / ca->mi.bucket_size, 187 190 .sectors = bucket_sectors_used(m),