1 // SPDX-License-Identifier: GPL-2.0 2 #ifndef NO_BCACHEFS_CHARDEV 3 4 #include "bcachefs.h" 5 #include "bcachefs_ioctl.h" 6 #include "buckets.h" 7 #include "chardev.h" 8 #include "journal.h" 9 #include "move.h" 10 #include "recovery.h" 11 #include "replicas.h" 12 #include "super.h" 13 #include "super-io.h" 14 #include "thread_with_file.h" 15 16 #include <linux/cdev.h> 17 #include <linux/device.h> 18 #include <linux/fs.h> 19 #include <linux/ioctl.h> 20 #include <linux/major.h> 21 #include <linux/sched/task.h> 22 #include <linux/slab.h> 23 #include <linux/uaccess.h> 24 25 /* returns with ref on ca->ref */ 26 static struct bch_dev *bch2_device_lookup(struct bch_fs *c, u64 dev, 27 unsigned flags) 28 { 29 struct bch_dev *ca; 30 31 if (flags & BCH_BY_INDEX) { 32 if (dev >= c->sb.nr_devices) 33 return ERR_PTR(-EINVAL); 34 35 rcu_read_lock(); 36 ca = rcu_dereference(c->devs[dev]); 37 if (ca) 38 percpu_ref_get(&ca->ref); 39 rcu_read_unlock(); 40 41 if (!ca) 42 return ERR_PTR(-EINVAL); 43 } else { 44 char *path; 45 46 path = strndup_user((const char __user *) 47 (unsigned long) dev, PATH_MAX); 48 if (IS_ERR(path)) 49 return ERR_CAST(path); 50 51 ca = bch2_dev_lookup(c, path); 52 kfree(path); 53 } 54 55 return ca; 56 } 57 58 #if 0 59 static long bch2_ioctl_assemble(struct bch_ioctl_assemble __user *user_arg) 60 { 61 struct bch_ioctl_assemble arg; 62 struct bch_fs *c; 63 u64 *user_devs = NULL; 64 char **devs = NULL; 65 unsigned i; 66 int ret = -EFAULT; 67 68 if (copy_from_user(&arg, user_arg, sizeof(arg))) 69 return -EFAULT; 70 71 if (arg.flags || arg.pad) 72 return -EINVAL; 73 74 user_devs = kmalloc_array(arg.nr_devs, sizeof(u64), GFP_KERNEL); 75 if (!user_devs) 76 return -ENOMEM; 77 78 devs = kcalloc(arg.nr_devs, sizeof(char *), GFP_KERNEL); 79 80 if (copy_from_user(user_devs, user_arg->devs, 81 sizeof(u64) * arg.nr_devs)) 82 goto err; 83 84 for (i = 0; i < arg.nr_devs; i++) { 85 devs[i] = strndup_user((const char __user *)(unsigned long) 86 user_devs[i], 87 PATH_MAX); 88 ret= PTR_ERR_OR_ZERO(devs[i]); 89 if (ret) 90 goto err; 91 } 92 93 c = bch2_fs_open(devs, arg.nr_devs, bch2_opts_empty()); 94 ret = PTR_ERR_OR_ZERO(c); 95 if (!ret) 96 closure_put(&c->cl); 97 err: 98 if (devs) 99 for (i = 0; i < arg.nr_devs; i++) 100 kfree(devs[i]); 101 kfree(devs); 102 return ret; 103 } 104 105 static long bch2_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg) 106 { 107 struct bch_ioctl_incremental arg; 108 const char *err; 109 char *path; 110 111 if (copy_from_user(&arg, user_arg, sizeof(arg))) 112 return -EFAULT; 113 114 if (arg.flags || arg.pad) 115 return -EINVAL; 116 117 path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX); 118 ret = PTR_ERR_OR_ZERO(path); 119 if (ret) 120 return ret; 121 122 err = bch2_fs_open_incremental(path); 123 kfree(path); 124 125 if (err) { 126 pr_err("Could not register bcachefs devices: %s", err); 127 return -EINVAL; 128 } 129 130 return 0; 131 } 132 #endif 133 134 struct fsck_thread { 135 struct thread_with_stdio thr; 136 struct bch_fs *c; 137 char **devs; 138 size_t nr_devs; 139 struct bch_opts opts; 140 }; 141 142 static void bch2_fsck_thread_exit(struct thread_with_stdio *_thr) 143 { 144 struct fsck_thread *thr = container_of(_thr, struct fsck_thread, thr); 145 if (thr->devs) 146 for (size_t i = 0; i < thr->nr_devs; i++) 147 kfree(thr->devs[i]); 148 kfree(thr->devs); 149 kfree(thr); 150 } 151 152 static int bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio) 153 { 154 struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr); 155 struct bch_fs *c = bch2_fs_open(thr->devs, thr->nr_devs, thr->opts); 156 157 if (IS_ERR(c)) 158 return PTR_ERR(c); 159 160 int ret = 0; 161 if (test_bit(BCH_FS_errors_fixed, &c->flags)) 162 ret |= 1; 163 if (test_bit(BCH_FS_error, &c->flags)) 164 ret |= 4; 165 166 bch2_fs_stop(c); 167 168 if (ret & 1) 169 bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: errors fixed\n", c->name); 170 if (ret & 4) 171 bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: still has errors\n", c->name); 172 173 return ret; 174 } 175 176 static const struct thread_with_stdio_ops bch2_offline_fsck_ops = { 177 .exit = bch2_fsck_thread_exit, 178 .fn = bch2_fsck_offline_thread_fn, 179 }; 180 181 static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_arg) 182 { 183 struct bch_ioctl_fsck_offline arg; 184 struct fsck_thread *thr = NULL; 185 u64 *devs = NULL; 186 long ret = 0; 187 188 if (copy_from_user(&arg, user_arg, sizeof(arg))) 189 return -EFAULT; 190 191 if (arg.flags) 192 return -EINVAL; 193 194 if (!capable(CAP_SYS_ADMIN)) 195 return -EPERM; 196 197 if (!(devs = kcalloc(arg.nr_devs, sizeof(*devs), GFP_KERNEL)) || 198 !(thr = kzalloc(sizeof(*thr), GFP_KERNEL)) || 199 !(thr->devs = kcalloc(arg.nr_devs, sizeof(*thr->devs), GFP_KERNEL))) { 200 ret = -ENOMEM; 201 goto err; 202 } 203 204 thr->opts = bch2_opts_empty(); 205 thr->nr_devs = arg.nr_devs; 206 207 if (copy_from_user(devs, &user_arg->devs[0], 208 array_size(sizeof(user_arg->devs[0]), arg.nr_devs))) { 209 ret = -EINVAL; 210 goto err; 211 } 212 213 for (size_t i = 0; i < arg.nr_devs; i++) { 214 thr->devs[i] = strndup_user((char __user *)(unsigned long) devs[i], PATH_MAX); 215 ret = PTR_ERR_OR_ZERO(thr->devs[i]); 216 if (ret) 217 goto err; 218 } 219 220 if (arg.opts) { 221 char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16); 222 223 ret = PTR_ERR_OR_ZERO(optstr) ?: 224 bch2_parse_mount_opts(NULL, &thr->opts, optstr); 225 kfree(optstr); 226 227 if (ret) 228 goto err; 229 } 230 231 opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio); 232 233 ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops); 234 err: 235 if (ret < 0) { 236 if (thr) 237 bch2_fsck_thread_exit(&thr->thr); 238 pr_err("ret %s", bch2_err_str(ret)); 239 } 240 kfree(devs); 241 return ret; 242 } 243 244 static long bch2_global_ioctl(unsigned cmd, void __user *arg) 245 { 246 long ret; 247 248 switch (cmd) { 249 #if 0 250 case BCH_IOCTL_ASSEMBLE: 251 return bch2_ioctl_assemble(arg); 252 case BCH_IOCTL_INCREMENTAL: 253 return bch2_ioctl_incremental(arg); 254 #endif 255 case BCH_IOCTL_FSCK_OFFLINE: { 256 ret = bch2_ioctl_fsck_offline(arg); 257 break; 258 } 259 default: 260 ret = -ENOTTY; 261 break; 262 } 263 264 if (ret < 0) 265 ret = bch2_err_class(ret); 266 return ret; 267 } 268 269 static long bch2_ioctl_query_uuid(struct bch_fs *c, 270 struct bch_ioctl_query_uuid __user *user_arg) 271 { 272 return copy_to_user_errcode(&user_arg->uuid, &c->sb.user_uuid, 273 sizeof(c->sb.user_uuid)); 274 } 275 276 #if 0 277 static long bch2_ioctl_start(struct bch_fs *c, struct bch_ioctl_start arg) 278 { 279 if (!capable(CAP_SYS_ADMIN)) 280 return -EPERM; 281 282 if (arg.flags || arg.pad) 283 return -EINVAL; 284 285 return bch2_fs_start(c); 286 } 287 288 static long bch2_ioctl_stop(struct bch_fs *c) 289 { 290 if (!capable(CAP_SYS_ADMIN)) 291 return -EPERM; 292 293 bch2_fs_stop(c); 294 return 0; 295 } 296 #endif 297 298 static long bch2_ioctl_disk_add(struct bch_fs *c, struct bch_ioctl_disk arg) 299 { 300 char *path; 301 int ret; 302 303 if (!capable(CAP_SYS_ADMIN)) 304 return -EPERM; 305 306 if (arg.flags || arg.pad) 307 return -EINVAL; 308 309 path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX); 310 ret = PTR_ERR_OR_ZERO(path); 311 if (ret) 312 return ret; 313 314 ret = bch2_dev_add(c, path); 315 kfree(path); 316 317 return ret; 318 } 319 320 static long bch2_ioctl_disk_remove(struct bch_fs *c, struct bch_ioctl_disk arg) 321 { 322 struct bch_dev *ca; 323 324 if (!capable(CAP_SYS_ADMIN)) 325 return -EPERM; 326 327 if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST| 328 BCH_FORCE_IF_METADATA_LOST| 329 BCH_FORCE_IF_DEGRADED| 330 BCH_BY_INDEX)) || 331 arg.pad) 332 return -EINVAL; 333 334 ca = bch2_device_lookup(c, arg.dev, arg.flags); 335 if (IS_ERR(ca)) 336 return PTR_ERR(ca); 337 338 return bch2_dev_remove(c, ca, arg.flags); 339 } 340 341 static long bch2_ioctl_disk_online(struct bch_fs *c, struct bch_ioctl_disk arg) 342 { 343 char *path; 344 int ret; 345 346 if (!capable(CAP_SYS_ADMIN)) 347 return -EPERM; 348 349 if (arg.flags || arg.pad) 350 return -EINVAL; 351 352 path = strndup_user((const char __user *)(unsigned long) arg.dev, PATH_MAX); 353 ret = PTR_ERR_OR_ZERO(path); 354 if (ret) 355 return ret; 356 357 ret = bch2_dev_online(c, path); 358 kfree(path); 359 return ret; 360 } 361 362 static long bch2_ioctl_disk_offline(struct bch_fs *c, struct bch_ioctl_disk arg) 363 { 364 struct bch_dev *ca; 365 int ret; 366 367 if (!capable(CAP_SYS_ADMIN)) 368 return -EPERM; 369 370 if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST| 371 BCH_FORCE_IF_METADATA_LOST| 372 BCH_FORCE_IF_DEGRADED| 373 BCH_BY_INDEX)) || 374 arg.pad) 375 return -EINVAL; 376 377 ca = bch2_device_lookup(c, arg.dev, arg.flags); 378 if (IS_ERR(ca)) 379 return PTR_ERR(ca); 380 381 ret = bch2_dev_offline(c, ca, arg.flags); 382 percpu_ref_put(&ca->ref); 383 return ret; 384 } 385 386 static long bch2_ioctl_disk_set_state(struct bch_fs *c, 387 struct bch_ioctl_disk_set_state arg) 388 { 389 struct bch_dev *ca; 390 int ret; 391 392 if (!capable(CAP_SYS_ADMIN)) 393 return -EPERM; 394 395 if ((arg.flags & ~(BCH_FORCE_IF_DATA_LOST| 396 BCH_FORCE_IF_METADATA_LOST| 397 BCH_FORCE_IF_DEGRADED| 398 BCH_BY_INDEX)) || 399 arg.pad[0] || arg.pad[1] || arg.pad[2] || 400 arg.new_state >= BCH_MEMBER_STATE_NR) 401 return -EINVAL; 402 403 ca = bch2_device_lookup(c, arg.dev, arg.flags); 404 if (IS_ERR(ca)) 405 return PTR_ERR(ca); 406 407 ret = bch2_dev_set_state(c, ca, arg.new_state, arg.flags); 408 if (ret) 409 bch_err(c, "Error setting device state: %s", bch2_err_str(ret)); 410 411 percpu_ref_put(&ca->ref); 412 return ret; 413 } 414 415 struct bch_data_ctx { 416 struct thread_with_file thr; 417 418 struct bch_fs *c; 419 struct bch_ioctl_data arg; 420 struct bch_move_stats stats; 421 }; 422 423 static int bch2_data_thread(void *arg) 424 { 425 struct bch_data_ctx *ctx = container_of(arg, struct bch_data_ctx, thr); 426 427 ctx->thr.ret = bch2_data_job(ctx->c, &ctx->stats, ctx->arg); 428 ctx->stats.data_type = U8_MAX; 429 return 0; 430 } 431 432 static int bch2_data_job_release(struct inode *inode, struct file *file) 433 { 434 struct bch_data_ctx *ctx = container_of(file->private_data, struct bch_data_ctx, thr); 435 436 bch2_thread_with_file_exit(&ctx->thr); 437 kfree(ctx); 438 return 0; 439 } 440 441 static ssize_t bch2_data_job_read(struct file *file, char __user *buf, 442 size_t len, loff_t *ppos) 443 { 444 struct bch_data_ctx *ctx = container_of(file->private_data, struct bch_data_ctx, thr); 445 struct bch_fs *c = ctx->c; 446 struct bch_ioctl_data_event e = { 447 .type = BCH_DATA_EVENT_PROGRESS, 448 .p.data_type = ctx->stats.data_type, 449 .p.btree_id = ctx->stats.pos.btree, 450 .p.pos = ctx->stats.pos.pos, 451 .p.sectors_done = atomic64_read(&ctx->stats.sectors_seen), 452 .p.sectors_total = bch2_fs_usage_read_short(c).used, 453 }; 454 455 if (len < sizeof(e)) 456 return -EINVAL; 457 458 return copy_to_user_errcode(buf, &e, sizeof(e)) ?: sizeof(e); 459 } 460 461 static const struct file_operations bcachefs_data_ops = { 462 .release = bch2_data_job_release, 463 .read = bch2_data_job_read, 464 .llseek = no_llseek, 465 }; 466 467 static long bch2_ioctl_data(struct bch_fs *c, 468 struct bch_ioctl_data arg) 469 { 470 struct bch_data_ctx *ctx; 471 int ret; 472 473 if (!capable(CAP_SYS_ADMIN)) 474 return -EPERM; 475 476 if (arg.op >= BCH_DATA_OP_NR || arg.flags) 477 return -EINVAL; 478 479 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 480 if (!ctx) 481 return -ENOMEM; 482 483 ctx->c = c; 484 ctx->arg = arg; 485 486 ret = bch2_run_thread_with_file(&ctx->thr, 487 &bcachefs_data_ops, 488 bch2_data_thread); 489 if (ret < 0) 490 kfree(ctx); 491 return ret; 492 } 493 494 static long bch2_ioctl_fs_usage(struct bch_fs *c, 495 struct bch_ioctl_fs_usage __user *user_arg) 496 { 497 struct bch_ioctl_fs_usage *arg = NULL; 498 struct bch_replicas_usage *dst_e, *dst_end; 499 struct bch_fs_usage_online *src; 500 u32 replica_entries_bytes; 501 unsigned i; 502 int ret = 0; 503 504 if (!test_bit(BCH_FS_started, &c->flags)) 505 return -EINVAL; 506 507 if (get_user(replica_entries_bytes, &user_arg->replica_entries_bytes)) 508 return -EFAULT; 509 510 arg = kzalloc(size_add(sizeof(*arg), replica_entries_bytes), GFP_KERNEL); 511 if (!arg) 512 return -ENOMEM; 513 514 src = bch2_fs_usage_read(c); 515 if (!src) { 516 ret = -ENOMEM; 517 goto err; 518 } 519 520 arg->capacity = c->capacity; 521 arg->used = bch2_fs_sectors_used(c, src); 522 arg->online_reserved = src->online_reserved; 523 524 for (i = 0; i < BCH_REPLICAS_MAX; i++) 525 arg->persistent_reserved[i] = src->u.persistent_reserved[i]; 526 527 dst_e = arg->replicas; 528 dst_end = (void *) arg->replicas + replica_entries_bytes; 529 530 for (i = 0; i < c->replicas.nr; i++) { 531 struct bch_replicas_entry_v1 *src_e = 532 cpu_replicas_entry(&c->replicas, i); 533 534 /* check that we have enough space for one replicas entry */ 535 if (dst_e + 1 > dst_end) { 536 ret = -ERANGE; 537 break; 538 } 539 540 dst_e->sectors = src->u.replicas[i]; 541 dst_e->r = *src_e; 542 543 /* recheck after setting nr_devs: */ 544 if (replicas_usage_next(dst_e) > dst_end) { 545 ret = -ERANGE; 546 break; 547 } 548 549 memcpy(dst_e->r.devs, src_e->devs, src_e->nr_devs); 550 551 dst_e = replicas_usage_next(dst_e); 552 } 553 554 arg->replica_entries_bytes = (void *) dst_e - (void *) arg->replicas; 555 556 percpu_up_read(&c->mark_lock); 557 kfree(src); 558 559 if (ret) 560 goto err; 561 562 ret = copy_to_user_errcode(user_arg, arg, 563 sizeof(*arg) + arg->replica_entries_bytes); 564 err: 565 kfree(arg); 566 return ret; 567 } 568 569 /* obsolete, didn't allow for new data types: */ 570 static long bch2_ioctl_dev_usage(struct bch_fs *c, 571 struct bch_ioctl_dev_usage __user *user_arg) 572 { 573 struct bch_ioctl_dev_usage arg; 574 struct bch_dev_usage src; 575 struct bch_dev *ca; 576 unsigned i; 577 578 if (!test_bit(BCH_FS_started, &c->flags)) 579 return -EINVAL; 580 581 if (copy_from_user(&arg, user_arg, sizeof(arg))) 582 return -EFAULT; 583 584 if ((arg.flags & ~BCH_BY_INDEX) || 585 arg.pad[0] || 586 arg.pad[1] || 587 arg.pad[2]) 588 return -EINVAL; 589 590 ca = bch2_device_lookup(c, arg.dev, arg.flags); 591 if (IS_ERR(ca)) 592 return PTR_ERR(ca); 593 594 src = bch2_dev_usage_read(ca); 595 596 arg.state = ca->mi.state; 597 arg.bucket_size = ca->mi.bucket_size; 598 arg.nr_buckets = ca->mi.nbuckets - ca->mi.first_bucket; 599 600 for (i = 0; i < BCH_DATA_NR; i++) { 601 arg.d[i].buckets = src.d[i].buckets; 602 arg.d[i].sectors = src.d[i].sectors; 603 arg.d[i].fragmented = src.d[i].fragmented; 604 } 605 606 percpu_ref_put(&ca->ref); 607 608 return copy_to_user_errcode(user_arg, &arg, sizeof(arg)); 609 } 610 611 static long bch2_ioctl_dev_usage_v2(struct bch_fs *c, 612 struct bch_ioctl_dev_usage_v2 __user *user_arg) 613 { 614 struct bch_ioctl_dev_usage_v2 arg; 615 struct bch_dev_usage src; 616 struct bch_dev *ca; 617 int ret = 0; 618 619 if (!test_bit(BCH_FS_started, &c->flags)) 620 return -EINVAL; 621 622 if (copy_from_user(&arg, user_arg, sizeof(arg))) 623 return -EFAULT; 624 625 if ((arg.flags & ~BCH_BY_INDEX) || 626 arg.pad[0] || 627 arg.pad[1] || 628 arg.pad[2]) 629 return -EINVAL; 630 631 ca = bch2_device_lookup(c, arg.dev, arg.flags); 632 if (IS_ERR(ca)) 633 return PTR_ERR(ca); 634 635 src = bch2_dev_usage_read(ca); 636 637 arg.state = ca->mi.state; 638 arg.bucket_size = ca->mi.bucket_size; 639 arg.nr_data_types = min(arg.nr_data_types, BCH_DATA_NR); 640 arg.nr_buckets = ca->mi.nbuckets - ca->mi.first_bucket; 641 642 ret = copy_to_user_errcode(user_arg, &arg, sizeof(arg)); 643 if (ret) 644 goto err; 645 646 for (unsigned i = 0; i < arg.nr_data_types; i++) { 647 struct bch_ioctl_dev_usage_type t = { 648 .buckets = src.d[i].buckets, 649 .sectors = src.d[i].sectors, 650 .fragmented = src.d[i].fragmented, 651 }; 652 653 ret = copy_to_user_errcode(&user_arg->d[i], &t, sizeof(t)); 654 if (ret) 655 goto err; 656 } 657 err: 658 percpu_ref_put(&ca->ref); 659 return ret; 660 } 661 662 static long bch2_ioctl_read_super(struct bch_fs *c, 663 struct bch_ioctl_read_super arg) 664 { 665 struct bch_dev *ca = NULL; 666 struct bch_sb *sb; 667 int ret = 0; 668 669 if (!capable(CAP_SYS_ADMIN)) 670 return -EPERM; 671 672 if ((arg.flags & ~(BCH_BY_INDEX|BCH_READ_DEV)) || 673 arg.pad) 674 return -EINVAL; 675 676 mutex_lock(&c->sb_lock); 677 678 if (arg.flags & BCH_READ_DEV) { 679 ca = bch2_device_lookup(c, arg.dev, arg.flags); 680 681 if (IS_ERR(ca)) { 682 ret = PTR_ERR(ca); 683 goto err; 684 } 685 686 sb = ca->disk_sb.sb; 687 } else { 688 sb = c->disk_sb.sb; 689 } 690 691 if (vstruct_bytes(sb) > arg.size) { 692 ret = -ERANGE; 693 goto err; 694 } 695 696 ret = copy_to_user_errcode((void __user *)(unsigned long)arg.sb, sb, 697 vstruct_bytes(sb)); 698 err: 699 if (!IS_ERR_OR_NULL(ca)) 700 percpu_ref_put(&ca->ref); 701 mutex_unlock(&c->sb_lock); 702 return ret; 703 } 704 705 static long bch2_ioctl_disk_get_idx(struct bch_fs *c, 706 struct bch_ioctl_disk_get_idx arg) 707 { 708 dev_t dev = huge_decode_dev(arg.dev); 709 710 if (!capable(CAP_SYS_ADMIN)) 711 return -EPERM; 712 713 if (!dev) 714 return -EINVAL; 715 716 for_each_online_member(c, ca) 717 if (ca->dev == dev) { 718 percpu_ref_put(&ca->io_ref); 719 return ca->dev_idx; 720 } 721 722 return -BCH_ERR_ENOENT_dev_idx_not_found; 723 } 724 725 static long bch2_ioctl_disk_resize(struct bch_fs *c, 726 struct bch_ioctl_disk_resize arg) 727 { 728 struct bch_dev *ca; 729 int ret; 730 731 if (!capable(CAP_SYS_ADMIN)) 732 return -EPERM; 733 734 if ((arg.flags & ~BCH_BY_INDEX) || 735 arg.pad) 736 return -EINVAL; 737 738 ca = bch2_device_lookup(c, arg.dev, arg.flags); 739 if (IS_ERR(ca)) 740 return PTR_ERR(ca); 741 742 ret = bch2_dev_resize(c, ca, arg.nbuckets); 743 744 percpu_ref_put(&ca->ref); 745 return ret; 746 } 747 748 static long bch2_ioctl_disk_resize_journal(struct bch_fs *c, 749 struct bch_ioctl_disk_resize_journal arg) 750 { 751 struct bch_dev *ca; 752 int ret; 753 754 if (!capable(CAP_SYS_ADMIN)) 755 return -EPERM; 756 757 if ((arg.flags & ~BCH_BY_INDEX) || 758 arg.pad) 759 return -EINVAL; 760 761 if (arg.nbuckets > U32_MAX) 762 return -EINVAL; 763 764 ca = bch2_device_lookup(c, arg.dev, arg.flags); 765 if (IS_ERR(ca)) 766 return PTR_ERR(ca); 767 768 ret = bch2_set_nr_journal_buckets(c, ca, arg.nbuckets); 769 770 percpu_ref_put(&ca->ref); 771 return ret; 772 } 773 774 static int bch2_fsck_online_thread_fn(struct thread_with_stdio *stdio) 775 { 776 struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr); 777 struct bch_fs *c = thr->c; 778 779 c->stdio_filter = current; 780 c->stdio = &thr->thr.stdio; 781 782 /* 783 * XXX: can we figure out a way to do this without mucking with c->opts? 784 */ 785 unsigned old_fix_errors = c->opts.fix_errors; 786 if (opt_defined(thr->opts, fix_errors)) 787 c->opts.fix_errors = thr->opts.fix_errors; 788 else 789 c->opts.fix_errors = FSCK_FIX_ask; 790 791 c->opts.fsck = true; 792 set_bit(BCH_FS_fsck_running, &c->flags); 793 794 c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info; 795 int ret = bch2_run_online_recovery_passes(c); 796 797 clear_bit(BCH_FS_fsck_running, &c->flags); 798 bch_err_fn(c, ret); 799 800 c->stdio = NULL; 801 c->stdio_filter = NULL; 802 c->opts.fix_errors = old_fix_errors; 803 804 up(&c->online_fsck_mutex); 805 bch2_ro_ref_put(c); 806 return ret; 807 } 808 809 static const struct thread_with_stdio_ops bch2_online_fsck_ops = { 810 .exit = bch2_fsck_thread_exit, 811 .fn = bch2_fsck_online_thread_fn, 812 }; 813 814 static long bch2_ioctl_fsck_online(struct bch_fs *c, 815 struct bch_ioctl_fsck_online arg) 816 { 817 struct fsck_thread *thr = NULL; 818 long ret = 0; 819 820 if (arg.flags) 821 return -EINVAL; 822 823 if (!capable(CAP_SYS_ADMIN)) 824 return -EPERM; 825 826 if (!bch2_ro_ref_tryget(c)) 827 return -EROFS; 828 829 if (down_trylock(&c->online_fsck_mutex)) { 830 bch2_ro_ref_put(c); 831 return -EAGAIN; 832 } 833 834 thr = kzalloc(sizeof(*thr), GFP_KERNEL); 835 if (!thr) { 836 ret = -ENOMEM; 837 goto err; 838 } 839 840 thr->c = c; 841 thr->opts = bch2_opts_empty(); 842 843 if (arg.opts) { 844 char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16); 845 846 ret = PTR_ERR_OR_ZERO(optstr) ?: 847 bch2_parse_mount_opts(c, &thr->opts, optstr); 848 kfree(optstr); 849 850 if (ret) 851 goto err; 852 } 853 854 ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_online_fsck_ops); 855 err: 856 if (ret < 0) { 857 bch_err_fn(c, ret); 858 if (thr) 859 bch2_fsck_thread_exit(&thr->thr); 860 up(&c->online_fsck_mutex); 861 bch2_ro_ref_put(c); 862 } 863 return ret; 864 } 865 866 #define BCH_IOCTL(_name, _argtype) \ 867 do { \ 868 _argtype i; \ 869 \ 870 if (copy_from_user(&i, arg, sizeof(i))) \ 871 return -EFAULT; \ 872 ret = bch2_ioctl_##_name(c, i); \ 873 goto out; \ 874 } while (0) 875 876 long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg) 877 { 878 long ret; 879 880 switch (cmd) { 881 case BCH_IOCTL_QUERY_UUID: 882 return bch2_ioctl_query_uuid(c, arg); 883 case BCH_IOCTL_FS_USAGE: 884 return bch2_ioctl_fs_usage(c, arg); 885 case BCH_IOCTL_DEV_USAGE: 886 return bch2_ioctl_dev_usage(c, arg); 887 case BCH_IOCTL_DEV_USAGE_V2: 888 return bch2_ioctl_dev_usage_v2(c, arg); 889 #if 0 890 case BCH_IOCTL_START: 891 BCH_IOCTL(start, struct bch_ioctl_start); 892 case BCH_IOCTL_STOP: 893 return bch2_ioctl_stop(c); 894 #endif 895 case BCH_IOCTL_READ_SUPER: 896 BCH_IOCTL(read_super, struct bch_ioctl_read_super); 897 case BCH_IOCTL_DISK_GET_IDX: 898 BCH_IOCTL(disk_get_idx, struct bch_ioctl_disk_get_idx); 899 } 900 901 if (!test_bit(BCH_FS_started, &c->flags)) 902 return -EINVAL; 903 904 switch (cmd) { 905 case BCH_IOCTL_DISK_ADD: 906 BCH_IOCTL(disk_add, struct bch_ioctl_disk); 907 case BCH_IOCTL_DISK_REMOVE: 908 BCH_IOCTL(disk_remove, struct bch_ioctl_disk); 909 case BCH_IOCTL_DISK_ONLINE: 910 BCH_IOCTL(disk_online, struct bch_ioctl_disk); 911 case BCH_IOCTL_DISK_OFFLINE: 912 BCH_IOCTL(disk_offline, struct bch_ioctl_disk); 913 case BCH_IOCTL_DISK_SET_STATE: 914 BCH_IOCTL(disk_set_state, struct bch_ioctl_disk_set_state); 915 case BCH_IOCTL_DATA: 916 BCH_IOCTL(data, struct bch_ioctl_data); 917 case BCH_IOCTL_DISK_RESIZE: 918 BCH_IOCTL(disk_resize, struct bch_ioctl_disk_resize); 919 case BCH_IOCTL_DISK_RESIZE_JOURNAL: 920 BCH_IOCTL(disk_resize_journal, struct bch_ioctl_disk_resize_journal); 921 case BCH_IOCTL_FSCK_ONLINE: 922 BCH_IOCTL(fsck_online, struct bch_ioctl_fsck_online); 923 default: 924 return -ENOTTY; 925 } 926 out: 927 if (ret < 0) 928 ret = bch2_err_class(ret); 929 return ret; 930 } 931 932 static DEFINE_IDR(bch_chardev_minor); 933 934 static long bch2_chardev_ioctl(struct file *filp, unsigned cmd, unsigned long v) 935 { 936 unsigned minor = iminor(file_inode(filp)); 937 struct bch_fs *c = minor < U8_MAX ? idr_find(&bch_chardev_minor, minor) : NULL; 938 void __user *arg = (void __user *) v; 939 940 return c 941 ? bch2_fs_ioctl(c, cmd, arg) 942 : bch2_global_ioctl(cmd, arg); 943 } 944 945 static const struct file_operations bch_chardev_fops = { 946 .owner = THIS_MODULE, 947 .unlocked_ioctl = bch2_chardev_ioctl, 948 .open = nonseekable_open, 949 }; 950 951 static int bch_chardev_major; 952 static struct class *bch_chardev_class; 953 static struct device *bch_chardev; 954 955 void bch2_fs_chardev_exit(struct bch_fs *c) 956 { 957 if (!IS_ERR_OR_NULL(c->chardev)) 958 device_unregister(c->chardev); 959 if (c->minor >= 0) 960 idr_remove(&bch_chardev_minor, c->minor); 961 } 962 963 int bch2_fs_chardev_init(struct bch_fs *c) 964 { 965 c->minor = idr_alloc(&bch_chardev_minor, c, 0, 0, GFP_KERNEL); 966 if (c->minor < 0) 967 return c->minor; 968 969 c->chardev = device_create(bch_chardev_class, NULL, 970 MKDEV(bch_chardev_major, c->minor), c, 971 "bcachefs%u-ctl", c->minor); 972 if (IS_ERR(c->chardev)) 973 return PTR_ERR(c->chardev); 974 975 return 0; 976 } 977 978 void bch2_chardev_exit(void) 979 { 980 if (!IS_ERR_OR_NULL(bch_chardev_class)) 981 device_destroy(bch_chardev_class, 982 MKDEV(bch_chardev_major, U8_MAX)); 983 if (!IS_ERR_OR_NULL(bch_chardev_class)) 984 class_destroy(bch_chardev_class); 985 if (bch_chardev_major > 0) 986 unregister_chrdev(bch_chardev_major, "bcachefs"); 987 } 988 989 int __init bch2_chardev_init(void) 990 { 991 bch_chardev_major = register_chrdev(0, "bcachefs-ctl", &bch_chardev_fops); 992 if (bch_chardev_major < 0) 993 return bch_chardev_major; 994 995 bch_chardev_class = class_create("bcachefs"); 996 if (IS_ERR(bch_chardev_class)) 997 return PTR_ERR(bch_chardev_class); 998 999 bch_chardev = device_create(bch_chardev_class, NULL, 1000 MKDEV(bch_chardev_major, U8_MAX), 1001 NULL, "bcachefs-ctl"); 1002 if (IS_ERR(bch_chardev)) 1003 return PTR_ERR(bch_chardev); 1004 1005 return 0; 1006 } 1007 1008 #endif /* NO_BCACHEFS_CHARDEV */ 1009