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