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

Configure Feed

Select the types of activity you want to include in your feed.

at v6.16 606 lines 18 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2 3#include "bcachefs.h" 4#include "btree_cache.h" 5#include "disk_groups.h" 6#include "error.h" 7#include "opts.h" 8#include "recovery_passes.h" 9#include "replicas.h" 10#include "sb-members.h" 11#include "super-io.h" 12 13int bch2_dev_missing_bkey(struct bch_fs *c, struct bkey_s_c k, unsigned dev) 14{ 15 struct printbuf buf = PRINTBUF; 16 bch2_log_msg_start(c, &buf); 17 18 prt_printf(&buf, "pointer to nonexistent device %u in key\n", dev); 19 bch2_bkey_val_to_text(&buf, c, k); 20 21 bool print = bch2_count_fsck_err(c, ptr_to_invalid_device, &buf); 22 23 int ret = bch2_run_explicit_recovery_pass(c, &buf, 24 BCH_RECOVERY_PASS_check_allocations, 0); 25 26 if (print) 27 bch2_print_str(c, KERN_ERR, buf.buf); 28 printbuf_exit(&buf); 29 return ret; 30} 31 32void bch2_dev_missing_atomic(struct bch_fs *c, unsigned dev) 33{ 34 if (dev != BCH_SB_MEMBER_INVALID) 35 bch2_fs_inconsistent(c, "pointer to nonexistent device %u", dev); 36} 37 38void bch2_dev_bucket_missing(struct bch_dev *ca, u64 bucket) 39{ 40 bch2_fs_inconsistent(ca->fs, 41 "pointer to nonexistent bucket %llu on device %s (valid range %u-%llu)", 42 bucket, ca->name, ca->mi.first_bucket, ca->mi.nbuckets); 43} 44 45#define x(t, n, ...) [n] = #t, 46static const char * const bch2_iops_measurements[] = { 47 BCH_IOPS_MEASUREMENTS() 48 NULL 49}; 50 51char * const bch2_member_error_strs[] = { 52 BCH_MEMBER_ERROR_TYPES() 53 NULL 54}; 55#undef x 56 57/* Code for bch_sb_field_members_v1: */ 58 59struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i) 60{ 61 return __bch2_members_v2_get_mut(bch2_sb_field_get(sb, members_v2), i); 62} 63 64static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i) 65{ 66 struct bch_member ret, *p = __bch2_members_v2_get_mut(mi, i); 67 memset(&ret, 0, sizeof(ret)); 68 memcpy(&ret, p, min_t(size_t, le16_to_cpu(mi->member_bytes), sizeof(ret))); 69 return ret; 70} 71 72static struct bch_member *members_v1_get_mut(struct bch_sb_field_members_v1 *mi, int i) 73{ 74 return (void *) mi->_members + (i * BCH_MEMBER_V1_BYTES); 75} 76 77static struct bch_member members_v1_get(struct bch_sb_field_members_v1 *mi, int i) 78{ 79 struct bch_member ret, *p = members_v1_get_mut(mi, i); 80 memset(&ret, 0, sizeof(ret)); 81 memcpy(&ret, p, min_t(size_t, BCH_MEMBER_V1_BYTES, sizeof(ret))); 82 return ret; 83} 84 85struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i) 86{ 87 struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(sb, members_v2); 88 if (mi2) 89 return members_v2_get(mi2, i); 90 struct bch_sb_field_members_v1 *mi1 = bch2_sb_field_get(sb, members_v1); 91 return members_v1_get(mi1, i); 92} 93 94static int sb_members_v2_resize_entries(struct bch_fs *c) 95{ 96 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); 97 98 if (le16_to_cpu(mi->member_bytes) < sizeof(struct bch_member)) { 99 unsigned u64s = DIV_ROUND_UP((sizeof(*mi) + sizeof(mi->_members[0]) * 100 c->disk_sb.sb->nr_devices), 8); 101 102 mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s); 103 if (!mi) 104 return bch_err_throw(c, ENOSPC_sb_members_v2); 105 106 for (int i = c->disk_sb.sb->nr_devices - 1; i >= 0; --i) { 107 void *dst = (void *) mi->_members + (i * sizeof(struct bch_member)); 108 memmove(dst, __bch2_members_v2_get_mut(mi, i), le16_to_cpu(mi->member_bytes)); 109 memset(dst + le16_to_cpu(mi->member_bytes), 110 0, (sizeof(struct bch_member) - le16_to_cpu(mi->member_bytes))); 111 } 112 mi->member_bytes = cpu_to_le16(sizeof(struct bch_member)); 113 } 114 return 0; 115} 116 117int bch2_sb_members_v2_init(struct bch_fs *c) 118{ 119 struct bch_sb_field_members_v1 *mi1; 120 struct bch_sb_field_members_v2 *mi2; 121 122 if (!bch2_sb_field_get(c->disk_sb.sb, members_v2)) { 123 mi2 = bch2_sb_field_resize(&c->disk_sb, members_v2, 124 DIV_ROUND_UP(sizeof(*mi2) + 125 sizeof(struct bch_member) * c->sb.nr_devices, 126 sizeof(u64))); 127 mi1 = bch2_sb_field_get(c->disk_sb.sb, members_v1); 128 memcpy(&mi2->_members[0], &mi1->_members[0], 129 BCH_MEMBER_V1_BYTES * c->sb.nr_devices); 130 memset(&mi2->pad[0], 0, sizeof(mi2->pad)); 131 mi2->member_bytes = cpu_to_le16(BCH_MEMBER_V1_BYTES); 132 } 133 134 return sb_members_v2_resize_entries(c); 135} 136 137int bch2_sb_members_cpy_v2_v1(struct bch_sb_handle *disk_sb) 138{ 139 struct bch_sb_field_members_v1 *mi1; 140 struct bch_sb_field_members_v2 *mi2; 141 142 if (BCH_SB_VERSION_INCOMPAT(disk_sb->sb) > bcachefs_metadata_version_extent_flags) { 143 bch2_sb_field_resize(disk_sb, members_v1, 0); 144 return 0; 145 } 146 147 mi1 = bch2_sb_field_resize(disk_sb, members_v1, 148 DIV_ROUND_UP(sizeof(*mi1) + BCH_MEMBER_V1_BYTES * 149 disk_sb->sb->nr_devices, sizeof(u64))); 150 if (!mi1) 151 return -BCH_ERR_ENOSPC_sb_members; 152 153 mi2 = bch2_sb_field_get(disk_sb->sb, members_v2); 154 155 for (unsigned i = 0; i < disk_sb->sb->nr_devices; i++) 156 memcpy(members_v1_get_mut(mi1, i), __bch2_members_v2_get_mut(mi2, i), BCH_MEMBER_V1_BYTES); 157 158 return 0; 159} 160 161static int validate_member(struct printbuf *err, 162 struct bch_member m, 163 struct bch_sb *sb, 164 int i) 165{ 166 if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) { 167 prt_printf(err, "device %u: too many buckets (got %llu, max %u)", 168 i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX); 169 return -BCH_ERR_invalid_sb_members; 170 } 171 172 if (le64_to_cpu(m.nbuckets) - 173 le16_to_cpu(m.first_bucket) < BCH_MIN_NR_NBUCKETS) { 174 prt_printf(err, "device %u: not enough buckets (got %llu, max %u)", 175 i, le64_to_cpu(m.nbuckets), BCH_MIN_NR_NBUCKETS); 176 return -BCH_ERR_invalid_sb_members; 177 } 178 179 if (le16_to_cpu(m.bucket_size) < 180 le16_to_cpu(sb->block_size)) { 181 prt_printf(err, "device %u: bucket size %u smaller than block size %u", 182 i, le16_to_cpu(m.bucket_size), le16_to_cpu(sb->block_size)); 183 return -BCH_ERR_invalid_sb_members; 184 } 185 186 if (le16_to_cpu(m.bucket_size) < 187 BCH_SB_BTREE_NODE_SIZE(sb)) { 188 prt_printf(err, "device %u: bucket size %u smaller than btree node size %llu", 189 i, le16_to_cpu(m.bucket_size), BCH_SB_BTREE_NODE_SIZE(sb)); 190 return -BCH_ERR_invalid_sb_members; 191 } 192 193 if (m.btree_bitmap_shift >= BCH_MI_BTREE_BITMAP_SHIFT_MAX) { 194 prt_printf(err, "device %u: invalid btree_bitmap_shift %u", i, m.btree_bitmap_shift); 195 return -BCH_ERR_invalid_sb_members; 196 } 197 198 if (BCH_MEMBER_FREESPACE_INITIALIZED(&m) && 199 sb->features[0] & cpu_to_le64(BIT_ULL(BCH_FEATURE_no_alloc_info))) { 200 prt_printf(err, "device %u: freespace initialized but fs has no alloc info", i); 201 return -BCH_ERR_invalid_sb_members; 202 } 203 204 return 0; 205} 206 207static void member_to_text(struct printbuf *out, 208 struct bch_member m, 209 struct bch_sb_field_disk_groups *gi, 210 struct bch_sb *sb, 211 int i) 212{ 213 unsigned data_have = bch2_sb_dev_has_data(sb, i); 214 u64 bucket_size = le16_to_cpu(m.bucket_size); 215 u64 device_size = le64_to_cpu(m.nbuckets) * bucket_size; 216 217 if (!bch2_member_alive(&m)) 218 return; 219 220 prt_printf(out, "Device:\t%u\n", i); 221 222 printbuf_indent_add(out, 2); 223 224 prt_printf(out, "Label:\t"); 225 if (BCH_MEMBER_GROUP(&m)) 226 bch2_disk_path_to_text_sb(out, sb, 227 BCH_MEMBER_GROUP(&m) - 1); 228 else 229 prt_printf(out, "(none)"); 230 prt_newline(out); 231 232 prt_printf(out, "UUID:\t"); 233 pr_uuid(out, m.uuid.b); 234 prt_newline(out); 235 236 prt_printf(out, "Size:\t"); 237 prt_units_u64(out, device_size << 9); 238 prt_newline(out); 239 240 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++) 241 prt_printf(out, "%s errors:\t%llu\n", bch2_member_error_strs[i], le64_to_cpu(m.errors[i])); 242 243 for (unsigned i = 0; i < BCH_IOPS_NR; i++) 244 prt_printf(out, "%s iops:\t%u\n", bch2_iops_measurements[i], le32_to_cpu(m.iops[i])); 245 246 prt_printf(out, "Bucket size:\t"); 247 prt_units_u64(out, bucket_size << 9); 248 prt_newline(out); 249 250 prt_printf(out, "First bucket:\t%u\n", le16_to_cpu(m.first_bucket)); 251 prt_printf(out, "Buckets:\t%llu\n", le64_to_cpu(m.nbuckets)); 252 253 prt_printf(out, "Last mount:\t"); 254 if (m.last_mount) 255 bch2_prt_datetime(out, le64_to_cpu(m.last_mount)); 256 else 257 prt_printf(out, "(never)"); 258 prt_newline(out); 259 260 prt_printf(out, "Last superblock write:\t%llu\n", le64_to_cpu(m.seq)); 261 262 prt_printf(out, "State:\t%s\n", 263 BCH_MEMBER_STATE(&m) < BCH_MEMBER_STATE_NR 264 ? bch2_member_states[BCH_MEMBER_STATE(&m)] 265 : "unknown"); 266 267 prt_printf(out, "Data allowed:\t"); 268 if (BCH_MEMBER_DATA_ALLOWED(&m)) 269 prt_bitflags(out, __bch2_data_types, BCH_MEMBER_DATA_ALLOWED(&m)); 270 else 271 prt_printf(out, "(none)"); 272 prt_newline(out); 273 274 prt_printf(out, "Has data:\t"); 275 if (data_have) 276 prt_bitflags(out, __bch2_data_types, data_have); 277 else 278 prt_printf(out, "(none)"); 279 prt_newline(out); 280 281 prt_printf(out, "Btree allocated bitmap blocksize:\t"); 282 if (m.btree_bitmap_shift < 64) 283 prt_units_u64(out, 1ULL << m.btree_bitmap_shift); 284 else 285 prt_printf(out, "(invalid shift %u)", m.btree_bitmap_shift); 286 prt_newline(out); 287 288 prt_printf(out, "Btree allocated bitmap:\t"); 289 bch2_prt_u64_base2_nbits(out, le64_to_cpu(m.btree_allocated_bitmap), 64); 290 prt_newline(out); 291 292 prt_printf(out, "Durability:\t%llu\n", BCH_MEMBER_DURABILITY(&m) ? BCH_MEMBER_DURABILITY(&m) - 1 : 1); 293 294 prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(&m)); 295 prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(&m)); 296 prt_printf(out, "Resize on mount:\t%llu\n", BCH_MEMBER_RESIZE_ON_MOUNT(&m)); 297 298 printbuf_indent_sub(out, 2); 299} 300 301static int bch2_sb_members_v1_validate(struct bch_sb *sb, struct bch_sb_field *f, 302 enum bch_validate_flags flags, struct printbuf *err) 303{ 304 struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1); 305 unsigned i; 306 307 if ((void *) members_v1_get_mut(mi, sb->nr_devices) > vstruct_end(&mi->field)) { 308 prt_printf(err, "too many devices for section size"); 309 return -BCH_ERR_invalid_sb_members; 310 } 311 312 for (i = 0; i < sb->nr_devices; i++) { 313 struct bch_member m = members_v1_get(mi, i); 314 315 int ret = validate_member(err, m, sb, i); 316 if (ret) 317 return ret; 318 } 319 320 return 0; 321} 322 323static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb, 324 struct bch_sb_field *f) 325{ 326 struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1); 327 struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); 328 329 if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { 330 prt_printf(out, "field ends before start of entries"); 331 return; 332 } 333 334 unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / sizeof(mi->_members[0]); 335 if (nr != sb->nr_devices) 336 prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); 337 338 for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) 339 member_to_text(out, members_v1_get(mi, i), gi, sb, i); 340} 341 342const struct bch_sb_field_ops bch_sb_field_ops_members_v1 = { 343 .validate = bch2_sb_members_v1_validate, 344 .to_text = bch2_sb_members_v1_to_text, 345}; 346 347static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb, 348 struct bch_sb_field *f) 349{ 350 struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2); 351 struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); 352 353 if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { 354 prt_printf(out, "field ends before start of entries"); 355 return; 356 } 357 358 if (!le16_to_cpu(mi->member_bytes)) { 359 prt_printf(out, "member_bytes 0"); 360 return; 361 } 362 363 unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / le16_to_cpu(mi->member_bytes); 364 if (nr != sb->nr_devices) 365 prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); 366 367 /* 368 * We call to_text() on superblock sections that haven't passed 369 * validate, so we can't trust sb->nr_devices. 370 */ 371 372 for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) 373 member_to_text(out, members_v2_get(mi, i), gi, sb, i); 374} 375 376static int bch2_sb_members_v2_validate(struct bch_sb *sb, struct bch_sb_field *f, 377 enum bch_validate_flags flags, struct printbuf *err) 378{ 379 struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2); 380 size_t mi_bytes = (void *) __bch2_members_v2_get_mut(mi, sb->nr_devices) - 381 (void *) mi; 382 383 if (mi_bytes > vstruct_bytes(&mi->field)) { 384 prt_printf(err, "section too small (%zu > %zu)", 385 mi_bytes, vstruct_bytes(&mi->field)); 386 return -BCH_ERR_invalid_sb_members; 387 } 388 389 for (unsigned i = 0; i < sb->nr_devices; i++) { 390 int ret = validate_member(err, members_v2_get(mi, i), sb, i); 391 if (ret) 392 return ret; 393 } 394 395 return 0; 396} 397 398const struct bch_sb_field_ops bch_sb_field_ops_members_v2 = { 399 .validate = bch2_sb_members_v2_validate, 400 .to_text = bch2_sb_members_v2_to_text, 401}; 402 403void bch2_sb_members_from_cpu(struct bch_fs *c) 404{ 405 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); 406 407 guard(rcu)(); 408 for_each_member_device_rcu(c, ca, NULL) { 409 struct bch_member *m = __bch2_members_v2_get_mut(mi, ca->dev_idx); 410 411 for (unsigned e = 0; e < BCH_MEMBER_ERROR_NR; e++) 412 m->errors[e] = cpu_to_le64(atomic64_read(&ca->errors[e])); 413 } 414} 415 416void bch2_dev_io_errors_to_text(struct printbuf *out, struct bch_dev *ca) 417{ 418 struct bch_fs *c = ca->fs; 419 struct bch_member m; 420 421 mutex_lock(&ca->fs->sb_lock); 422 m = bch2_sb_member_get(c->disk_sb.sb, ca->dev_idx); 423 mutex_unlock(&ca->fs->sb_lock); 424 425 printbuf_tabstop_push(out, 12); 426 427 prt_str(out, "IO errors since filesystem creation"); 428 prt_newline(out); 429 430 printbuf_indent_add(out, 2); 431 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++) 432 prt_printf(out, "%s:\t%llu\n", bch2_member_error_strs[i], atomic64_read(&ca->errors[i])); 433 printbuf_indent_sub(out, 2); 434 435 prt_str(out, "IO errors since "); 436 bch2_pr_time_units(out, (ktime_get_real_seconds() - le64_to_cpu(m.errors_reset_time)) * NSEC_PER_SEC); 437 prt_str(out, " ago"); 438 prt_newline(out); 439 440 printbuf_indent_add(out, 2); 441 for (unsigned i = 0; i < BCH_MEMBER_ERROR_NR; i++) 442 prt_printf(out, "%s:\t%llu\n", bch2_member_error_strs[i], 443 atomic64_read(&ca->errors[i]) - le64_to_cpu(m.errors_at_reset[i])); 444 printbuf_indent_sub(out, 2); 445} 446 447void bch2_dev_errors_reset(struct bch_dev *ca) 448{ 449 struct bch_fs *c = ca->fs; 450 struct bch_member *m; 451 452 mutex_lock(&c->sb_lock); 453 m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx); 454 for (unsigned i = 0; i < ARRAY_SIZE(m->errors_at_reset); i++) 455 m->errors_at_reset[i] = cpu_to_le64(atomic64_read(&ca->errors[i])); 456 m->errors_reset_time = cpu_to_le64(ktime_get_real_seconds()); 457 458 bch2_write_super(c); 459 mutex_unlock(&c->sb_lock); 460} 461 462/* 463 * Per member "range has btree nodes" bitmap: 464 * 465 * This is so that if we ever have to run the btree node scan to repair we don't 466 * have to scan full devices: 467 */ 468 469bool bch2_dev_btree_bitmap_marked(struct bch_fs *c, struct bkey_s_c k) 470{ 471 guard(rcu)(); 472 bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) { 473 struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev); 474 if (ca && 475 !bch2_dev_btree_bitmap_marked_sectors(ca, ptr->offset, btree_sectors(c))) 476 return false; 477 } 478 return true; 479} 480 481static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, unsigned dev, 482 u64 start, unsigned sectors) 483{ 484 struct bch_member *m = __bch2_members_v2_get_mut(mi, dev); 485 u64 bitmap = le64_to_cpu(m->btree_allocated_bitmap); 486 487 u64 end = start + sectors; 488 489 int resize = ilog2(roundup_pow_of_two(end)) - (m->btree_bitmap_shift + 6); 490 if (resize > 0) { 491 u64 new_bitmap = 0; 492 493 for (unsigned i = 0; i < 64; i++) 494 if (bitmap & BIT_ULL(i)) 495 new_bitmap |= BIT_ULL(i >> resize); 496 bitmap = new_bitmap; 497 m->btree_bitmap_shift += resize; 498 } 499 500 BUG_ON(m->btree_bitmap_shift >= BCH_MI_BTREE_BITMAP_SHIFT_MAX); 501 BUG_ON(end > 64ULL << m->btree_bitmap_shift); 502 503 for (unsigned bit = start >> m->btree_bitmap_shift; 504 (u64) bit << m->btree_bitmap_shift < end; 505 bit++) 506 bitmap |= BIT_ULL(bit); 507 508 m->btree_allocated_bitmap = cpu_to_le64(bitmap); 509} 510 511void bch2_dev_btree_bitmap_mark(struct bch_fs *c, struct bkey_s_c k) 512{ 513 lockdep_assert_held(&c->sb_lock); 514 515 struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); 516 bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) { 517 if (!bch2_member_exists(c->disk_sb.sb, ptr->dev)) 518 continue; 519 520 __bch2_dev_btree_bitmap_mark(mi, ptr->dev, ptr->offset, btree_sectors(c)); 521 } 522} 523 524unsigned bch2_sb_nr_devices(const struct bch_sb *sb) 525{ 526 unsigned nr = 0; 527 528 for (unsigned i = 0; i < sb->nr_devices; i++) 529 nr += bch2_member_exists((struct bch_sb *) sb, i); 530 return nr; 531} 532 533int bch2_sb_member_alloc(struct bch_fs *c) 534{ 535 unsigned dev_idx = c->sb.nr_devices; 536 struct bch_sb_field_members_v2 *mi; 537 unsigned nr_devices; 538 unsigned u64s; 539 int best = -1; 540 u64 best_last_mount = 0; 541 unsigned nr_deleted = 0; 542 543 if (dev_idx < BCH_SB_MEMBERS_MAX) 544 goto have_slot; 545 546 for (dev_idx = 0; dev_idx < BCH_SB_MEMBERS_MAX; dev_idx++) { 547 /* eventually BCH_SB_MEMBERS_MAX will be raised */ 548 if (dev_idx == BCH_SB_MEMBER_INVALID) 549 continue; 550 551 struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, dev_idx); 552 553 nr_deleted += uuid_equal(&m.uuid, &BCH_SB_MEMBER_DELETED_UUID); 554 555 if (!bch2_is_zero(&m.uuid, sizeof(m.uuid))) 556 continue; 557 558 u64 last_mount = le64_to_cpu(m.last_mount); 559 if (best < 0 || last_mount < best_last_mount) { 560 best = dev_idx; 561 best_last_mount = last_mount; 562 } 563 } 564 if (best >= 0) { 565 dev_idx = best; 566 goto have_slot; 567 } 568 569 if (nr_deleted) 570 bch_err(c, "unable to allocate new member, but have %u deleted: run fsck", 571 nr_deleted); 572 573 return -BCH_ERR_ENOSPC_sb_members; 574have_slot: 575 nr_devices = max_t(unsigned, dev_idx + 1, c->sb.nr_devices); 576 577 mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); 578 u64s = DIV_ROUND_UP(sizeof(struct bch_sb_field_members_v2) + 579 le16_to_cpu(mi->member_bytes) * nr_devices, sizeof(u64)); 580 581 mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s); 582 if (!mi) 583 return -BCH_ERR_ENOSPC_sb_members; 584 585 c->disk_sb.sb->nr_devices = nr_devices; 586 return dev_idx; 587} 588 589void bch2_sb_members_clean_deleted(struct bch_fs *c) 590{ 591 mutex_lock(&c->sb_lock); 592 bool write_sb = false; 593 594 for (unsigned i = 0; i < c->sb.nr_devices; i++) { 595 struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, i); 596 597 if (uuid_equal(&m->uuid, &BCH_SB_MEMBER_DELETED_UUID)) { 598 memset(&m->uuid, 0, sizeof(m->uuid)); 599 write_sb = true; 600 } 601 } 602 603 if (write_sb) 604 bch2_write_super(c); 605 mutex_unlock(&c->sb_lock); 606}