1 // SPDX-License-Identifier: GPL-2.0 2 #include "bcachefs.h" 3 #include "disk_groups.h" 4 #include "sb-members.h" 5 #include "super-io.h" 6 7 #include <linux/sort.h> 8 9 static int group_cmp(const void *_l, const void *_r) 10 { 11 const struct bch_disk_group *l = _l; 12 const struct bch_disk_group *r = _r; 13 14 return ((BCH_GROUP_DELETED(l) > BCH_GROUP_DELETED(r)) - 15 (BCH_GROUP_DELETED(l) < BCH_GROUP_DELETED(r))) ?: 16 ((BCH_GROUP_PARENT(l) > BCH_GROUP_PARENT(r)) - 17 (BCH_GROUP_PARENT(l) < BCH_GROUP_PARENT(r))) ?: 18 strncmp(l->label, r->label, sizeof(l->label)); 19 } 20 21 static int bch2_sb_disk_groups_validate(struct bch_sb *sb, 22 struct bch_sb_field *f, 23 struct printbuf *err) 24 { 25 struct bch_sb_field_disk_groups *groups = 26 field_to_type(f, disk_groups); 27 struct bch_disk_group *g, *sorted = NULL; 28 unsigned nr_groups = disk_groups_nr(groups); 29 unsigned i, len; 30 int ret = 0; 31 32 for (i = 0; i < sb->nr_devices; i++) { 33 struct bch_member m = bch2_sb_member_get(sb, i); 34 unsigned group_id; 35 36 if (!BCH_MEMBER_GROUP(&m)) 37 continue; 38 39 group_id = BCH_MEMBER_GROUP(&m) - 1; 40 41 if (group_id >= nr_groups) { 42 prt_printf(err, "disk %u has invalid label %u (have %u)", 43 i, group_id, nr_groups); 44 return -BCH_ERR_invalid_sb_disk_groups; 45 } 46 47 if (BCH_GROUP_DELETED(&groups->entries[group_id])) { 48 prt_printf(err, "disk %u has deleted label %u", i, group_id); 49 return -BCH_ERR_invalid_sb_disk_groups; 50 } 51 } 52 53 if (!nr_groups) 54 return 0; 55 56 for (i = 0; i < nr_groups; i++) { 57 g = groups->entries + i; 58 59 if (BCH_GROUP_DELETED(g)) 60 continue; 61 62 len = strnlen(g->label, sizeof(g->label)); 63 if (!len) { 64 prt_printf(err, "label %u empty", i); 65 return -BCH_ERR_invalid_sb_disk_groups; 66 } 67 } 68 69 sorted = kmalloc_array(nr_groups, sizeof(*sorted), GFP_KERNEL); 70 if (!sorted) 71 return -BCH_ERR_ENOMEM_disk_groups_validate; 72 73 memcpy(sorted, groups->entries, nr_groups * sizeof(*sorted)); 74 sort(sorted, nr_groups, sizeof(*sorted), group_cmp, NULL); 75 76 for (g = sorted; g + 1 < sorted + nr_groups; g++) 77 if (!BCH_GROUP_DELETED(g) && 78 !group_cmp(&g[0], &g[1])) { 79 prt_printf(err, "duplicate label %llu.%.*s", 80 BCH_GROUP_PARENT(g), 81 (int) sizeof(g->label), g->label); 82 ret = -BCH_ERR_invalid_sb_disk_groups; 83 goto err; 84 } 85 err: 86 kfree(sorted); 87 return ret; 88 } 89 90 void bch2_disk_groups_to_text(struct printbuf *out, struct bch_fs *c) 91 { 92 out->atomic++; 93 rcu_read_lock(); 94 95 struct bch_disk_groups_cpu *g = rcu_dereference(c->disk_groups); 96 if (!g) 97 goto out; 98 99 for (unsigned i = 0; i < g->nr; i++) { 100 if (i) 101 prt_printf(out, " "); 102 103 if (g->entries[i].deleted) { 104 prt_printf(out, "[deleted]"); 105 continue; 106 } 107 108 prt_printf(out, "[parent %d devs", g->entries[i].parent); 109 for_each_member_device_rcu(c, ca, &g->entries[i].devs) 110 prt_printf(out, " %s", ca->name); 111 prt_printf(out, "]"); 112 } 113 114 out: 115 rcu_read_unlock(); 116 out->atomic--; 117 } 118 119 static void bch2_sb_disk_groups_to_text(struct printbuf *out, 120 struct bch_sb *sb, 121 struct bch_sb_field *f) 122 { 123 struct bch_sb_field_disk_groups *groups = 124 field_to_type(f, disk_groups); 125 struct bch_disk_group *g; 126 unsigned nr_groups = disk_groups_nr(groups); 127 128 for (g = groups->entries; 129 g < groups->entries + nr_groups; 130 g++) { 131 if (g != groups->entries) 132 prt_printf(out, " "); 133 134 if (BCH_GROUP_DELETED(g)) 135 prt_printf(out, "[deleted]"); 136 else 137 prt_printf(out, "[parent %llu name %s]", 138 BCH_GROUP_PARENT(g), g->label); 139 } 140 } 141 142 const struct bch_sb_field_ops bch_sb_field_ops_disk_groups = { 143 .validate = bch2_sb_disk_groups_validate, 144 .to_text = bch2_sb_disk_groups_to_text 145 }; 146 147 int bch2_sb_disk_groups_to_cpu(struct bch_fs *c) 148 { 149 struct bch_sb_field_disk_groups *groups; 150 struct bch_disk_groups_cpu *cpu_g, *old_g; 151 unsigned i, g, nr_groups; 152 153 lockdep_assert_held(&c->sb_lock); 154 155 groups = bch2_sb_field_get(c->disk_sb.sb, disk_groups); 156 nr_groups = disk_groups_nr(groups); 157 158 if (!groups) 159 return 0; 160 161 cpu_g = kzalloc(struct_size(cpu_g, entries, nr_groups), GFP_KERNEL); 162 if (!cpu_g) 163 return -BCH_ERR_ENOMEM_disk_groups_to_cpu; 164 165 cpu_g->nr = nr_groups; 166 167 for (i = 0; i < nr_groups; i++) { 168 struct bch_disk_group *src = &groups->entries[i]; 169 struct bch_disk_group_cpu *dst = &cpu_g->entries[i]; 170 171 dst->deleted = BCH_GROUP_DELETED(src); 172 dst->parent = BCH_GROUP_PARENT(src); 173 memcpy(dst->label, src->label, sizeof(dst->label)); 174 } 175 176 for (i = 0; i < c->disk_sb.sb->nr_devices; i++) { 177 struct bch_member m = bch2_sb_member_get(c->disk_sb.sb, i); 178 struct bch_disk_group_cpu *dst; 179 180 if (!bch2_member_exists(&m)) 181 continue; 182 183 g = BCH_MEMBER_GROUP(&m); 184 while (g) { 185 dst = &cpu_g->entries[g - 1]; 186 __set_bit(i, dst->devs.d); 187 g = dst->parent; 188 } 189 } 190 191 old_g = rcu_dereference_protected(c->disk_groups, 192 lockdep_is_held(&c->sb_lock)); 193 rcu_assign_pointer(c->disk_groups, cpu_g); 194 if (old_g) 195 kfree_rcu(old_g, rcu); 196 197 return 0; 198 } 199 200 const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *c, unsigned target) 201 { 202 struct target t = target_decode(target); 203 struct bch_devs_mask *devs; 204 205 rcu_read_lock(); 206 207 switch (t.type) { 208 case TARGET_NULL: 209 devs = NULL; 210 break; 211 case TARGET_DEV: { 212 struct bch_dev *ca = t.dev < c->sb.nr_devices 213 ? rcu_dereference(c->devs[t.dev]) 214 : NULL; 215 devs = ca ? &ca->self : NULL; 216 break; 217 } 218 case TARGET_GROUP: { 219 struct bch_disk_groups_cpu *g = rcu_dereference(c->disk_groups); 220 221 devs = g && t.group < g->nr && !g->entries[t.group].deleted 222 ? &g->entries[t.group].devs 223 : NULL; 224 break; 225 } 226 default: 227 BUG(); 228 } 229 230 rcu_read_unlock(); 231 232 return devs; 233 } 234 235 bool bch2_dev_in_target(struct bch_fs *c, unsigned dev, unsigned target) 236 { 237 struct target t = target_decode(target); 238 239 switch (t.type) { 240 case TARGET_NULL: 241 return false; 242 case TARGET_DEV: 243 return dev == t.dev; 244 case TARGET_GROUP: { 245 struct bch_disk_groups_cpu *g; 246 const struct bch_devs_mask *m; 247 bool ret; 248 249 rcu_read_lock(); 250 g = rcu_dereference(c->disk_groups); 251 m = g && t.group < g->nr && !g->entries[t.group].deleted 252 ? &g->entries[t.group].devs 253 : NULL; 254 255 ret = m ? test_bit(dev, m->d) : false; 256 rcu_read_unlock(); 257 258 return ret; 259 } 260 default: 261 BUG(); 262 } 263 } 264 265 static int __bch2_disk_group_find(struct bch_sb_field_disk_groups *groups, 266 unsigned parent, 267 const char *name, unsigned namelen) 268 { 269 unsigned i, nr_groups = disk_groups_nr(groups); 270 271 if (!namelen || namelen > BCH_SB_LABEL_SIZE) 272 return -EINVAL; 273 274 for (i = 0; i < nr_groups; i++) { 275 struct bch_disk_group *g = groups->entries + i; 276 277 if (BCH_GROUP_DELETED(g)) 278 continue; 279 280 if (!BCH_GROUP_DELETED(g) && 281 BCH_GROUP_PARENT(g) == parent && 282 strnlen(g->label, sizeof(g->label)) == namelen && 283 !memcmp(name, g->label, namelen)) 284 return i; 285 } 286 287 return -1; 288 } 289 290 static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent, 291 const char *name, unsigned namelen) 292 { 293 struct bch_sb_field_disk_groups *groups = 294 bch2_sb_field_get(sb->sb, disk_groups); 295 unsigned i, nr_groups = disk_groups_nr(groups); 296 struct bch_disk_group *g; 297 298 if (!namelen || namelen > BCH_SB_LABEL_SIZE) 299 return -EINVAL; 300 301 for (i = 0; 302 i < nr_groups && !BCH_GROUP_DELETED(&groups->entries[i]); 303 i++) 304 ; 305 306 if (i == nr_groups) { 307 unsigned u64s = 308 (sizeof(struct bch_sb_field_disk_groups) + 309 sizeof(struct bch_disk_group) * (nr_groups + 1)) / 310 sizeof(u64); 311 312 groups = bch2_sb_field_resize(sb, disk_groups, u64s); 313 if (!groups) 314 return -BCH_ERR_ENOSPC_disk_label_add; 315 316 nr_groups = disk_groups_nr(groups); 317 } 318 319 BUG_ON(i >= nr_groups); 320 321 g = &groups->entries[i]; 322 323 memcpy(g->label, name, namelen); 324 if (namelen < sizeof(g->label)) 325 g->label[namelen] = '\0'; 326 SET_BCH_GROUP_DELETED(g, 0); 327 SET_BCH_GROUP_PARENT(g, parent); 328 SET_BCH_GROUP_DATA_ALLOWED(g, ~0); 329 330 return i; 331 } 332 333 int bch2_disk_path_find(struct bch_sb_handle *sb, const char *name) 334 { 335 struct bch_sb_field_disk_groups *groups = 336 bch2_sb_field_get(sb->sb, disk_groups); 337 int v = -1; 338 339 do { 340 const char *next = strchrnul(name, '.'); 341 unsigned len = next - name; 342 343 if (*next == '.') 344 next++; 345 346 v = __bch2_disk_group_find(groups, v + 1, name, len); 347 name = next; 348 } while (*name && v >= 0); 349 350 return v; 351 } 352 353 int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name) 354 { 355 struct bch_sb_field_disk_groups *groups; 356 unsigned parent = 0; 357 int v = -1; 358 359 do { 360 const char *next = strchrnul(name, '.'); 361 unsigned len = next - name; 362 363 if (*next == '.') 364 next++; 365 366 groups = bch2_sb_field_get(sb->sb, disk_groups); 367 368 v = __bch2_disk_group_find(groups, parent, name, len); 369 if (v < 0) 370 v = __bch2_disk_group_add(sb, parent, name, len); 371 if (v < 0) 372 return v; 373 374 parent = v + 1; 375 name = next; 376 } while (*name && v >= 0); 377 378 return v; 379 } 380 381 void bch2_disk_path_to_text(struct printbuf *out, struct bch_fs *c, unsigned v) 382 { 383 struct bch_disk_groups_cpu *groups; 384 struct bch_disk_group_cpu *g; 385 unsigned nr = 0; 386 u16 path[32]; 387 388 out->atomic++; 389 rcu_read_lock(); 390 groups = rcu_dereference(c->disk_groups); 391 if (!groups) 392 goto invalid; 393 394 while (1) { 395 if (nr == ARRAY_SIZE(path)) 396 goto invalid; 397 398 if (v >= groups->nr) 399 goto invalid; 400 401 g = groups->entries + v; 402 403 if (g->deleted) 404 goto invalid; 405 406 path[nr++] = v; 407 408 if (!g->parent) 409 break; 410 411 v = g->parent - 1; 412 } 413 414 while (nr) { 415 v = path[--nr]; 416 g = groups->entries + v; 417 418 prt_printf(out, "%.*s", (int) sizeof(g->label), g->label); 419 if (nr) 420 prt_printf(out, "."); 421 } 422 out: 423 rcu_read_unlock(); 424 out->atomic--; 425 return; 426 invalid: 427 prt_printf(out, "invalid label %u", v); 428 goto out; 429 } 430 431 void bch2_disk_path_to_text_sb(struct printbuf *out, struct bch_sb *sb, unsigned v) 432 { 433 struct bch_sb_field_disk_groups *groups = 434 bch2_sb_field_get(sb, disk_groups); 435 struct bch_disk_group *g; 436 unsigned nr = 0; 437 u16 path[32]; 438 439 while (1) { 440 if (nr == ARRAY_SIZE(path)) 441 goto inval; 442 443 if (v >= disk_groups_nr(groups)) 444 goto inval; 445 446 g = groups->entries + v; 447 448 if (BCH_GROUP_DELETED(g)) 449 goto inval; 450 451 path[nr++] = v; 452 453 if (!BCH_GROUP_PARENT(g)) 454 break; 455 456 v = BCH_GROUP_PARENT(g) - 1; 457 } 458 459 while (nr) { 460 v = path[--nr]; 461 g = groups->entries + v; 462 463 prt_printf(out, "%.*s", (int) sizeof(g->label), g->label); 464 if (nr) 465 prt_printf(out, "."); 466 } 467 return; 468 inval: 469 prt_printf(out, "invalid label %u", v); 470 } 471 472 int __bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name) 473 { 474 struct bch_member *mi; 475 int ret, v = -1; 476 477 if (!strlen(name) || !strcmp(name, "none")) 478 return 0; 479 480 v = bch2_disk_path_find_or_create(&c->disk_sb, name); 481 if (v < 0) 482 return v; 483 484 ret = bch2_sb_disk_groups_to_cpu(c); 485 if (ret) 486 return ret; 487 488 mi = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx); 489 SET_BCH_MEMBER_GROUP(mi, v + 1); 490 return 0; 491 } 492 493 int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name) 494 { 495 int ret; 496 497 mutex_lock(&c->sb_lock); 498 ret = __bch2_dev_group_set(c, ca, name) ?: 499 bch2_write_super(c); 500 mutex_unlock(&c->sb_lock); 501 502 return ret; 503 } 504 505 int bch2_opt_target_parse(struct bch_fs *c, const char *val, u64 *res, 506 struct printbuf *err) 507 { 508 struct bch_dev *ca; 509 int g; 510 511 if (!val) 512 return -EINVAL; 513 514 if (!c) 515 return 0; 516 517 if (!strlen(val) || !strcmp(val, "none")) { 518 *res = 0; 519 return 0; 520 } 521 522 /* Is it a device? */ 523 ca = bch2_dev_lookup(c, val); 524 if (!IS_ERR(ca)) { 525 *res = dev_to_target(ca->dev_idx); 526 percpu_ref_put(&ca->ref); 527 return 0; 528 } 529 530 mutex_lock(&c->sb_lock); 531 g = bch2_disk_path_find(&c->disk_sb, val); 532 mutex_unlock(&c->sb_lock); 533 534 if (g >= 0) { 535 *res = group_to_target(g); 536 return 0; 537 } 538 539 return -EINVAL; 540 } 541 542 void bch2_target_to_text(struct printbuf *out, struct bch_fs *c, unsigned v) 543 { 544 struct target t = target_decode(v); 545 546 switch (t.type) { 547 case TARGET_NULL: 548 prt_printf(out, "none"); 549 break; 550 case TARGET_DEV: { 551 struct bch_dev *ca; 552 553 out->atomic++; 554 rcu_read_lock(); 555 ca = t.dev < c->sb.nr_devices 556 ? rcu_dereference(c->devs[t.dev]) 557 : NULL; 558 559 if (ca && percpu_ref_tryget(&ca->io_ref)) { 560 prt_printf(out, "/dev/%s", ca->name); 561 percpu_ref_put(&ca->io_ref); 562 } else if (ca) { 563 prt_printf(out, "offline device %u", t.dev); 564 } else { 565 prt_printf(out, "invalid device %u", t.dev); 566 } 567 568 rcu_read_unlock(); 569 out->atomic--; 570 break; 571 } 572 case TARGET_GROUP: 573 bch2_disk_path_to_text(out, c, t.group); 574 break; 575 default: 576 BUG(); 577 } 578 } 579 580 static void bch2_target_to_text_sb(struct printbuf *out, struct bch_sb *sb, unsigned v) 581 { 582 struct target t = target_decode(v); 583 584 switch (t.type) { 585 case TARGET_NULL: 586 prt_printf(out, "none"); 587 break; 588 case TARGET_DEV: { 589 struct bch_member m = bch2_sb_member_get(sb, t.dev); 590 591 if (bch2_dev_exists(sb, t.dev)) { 592 prt_printf(out, "Device "); 593 pr_uuid(out, m.uuid.b); 594 prt_printf(out, " (%u)", t.dev); 595 } else { 596 prt_printf(out, "Bad device %u", t.dev); 597 } 598 break; 599 } 600 case TARGET_GROUP: 601 bch2_disk_path_to_text_sb(out, sb, t.group); 602 break; 603 default: 604 BUG(); 605 } 606 } 607 608 void bch2_opt_target_to_text(struct printbuf *out, 609 struct bch_fs *c, 610 struct bch_sb *sb, 611 u64 v) 612 { 613 if (c) 614 bch2_target_to_text(out, c, v); 615 else 616 bch2_target_to_text_sb(out, sb, v); 617 } 618