]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_migrate.c
Update bcachefs sources to 386f00b639 bcachefs: Snapshot creation, deletion
[bcachefs-tools-debian] / cmd_migrate.c
1 #include <dirent.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <getopt.h>
5 #include <string.h>
6 #include <sys/xattr.h>
7 #include <sys/ioctl.h>
8 #include <sys/stat.h>
9 #include <sys/sysmacros.h>
10 #include <sys/types.h>
11 #include <sys/vfs.h>
12 #include <unistd.h>
13
14 #include <linux/fiemap.h>
15 #include <linux/fs.h>
16 #include <linux/stat.h>
17
18 #include <uuid/uuid.h>
19
20 #include "cmds.h"
21 #include "crypto.h"
22 #include "libbcachefs.h"
23
24 #include <linux/dcache.h>
25 #include <linux/generic-radix-tree.h>
26 #include <linux/xattr.h>
27 #include "libbcachefs/bcachefs.h"
28 #include "libbcachefs/alloc_background.h"
29 #include "libbcachefs/alloc_foreground.h"
30 #include "libbcachefs/btree_update.h"
31 #include "libbcachefs/buckets.h"
32 #include "libbcachefs/dirent.h"
33 #include "libbcachefs/fs-common.h"
34 #include "libbcachefs/inode.h"
35 #include "libbcachefs/io.h"
36 #include "libbcachefs/replicas.h"
37 #include "libbcachefs/str_hash.h"
38 #include "libbcachefs/super.h"
39 #include "libbcachefs/xattr.h"
40
41 /* XXX cut and pasted from fsck.c */
42 #define QSTR(n) { { { .len = strlen(n) } }, .name = n }
43
44 static char *dev_t_to_path(dev_t dev)
45 {
46         char link[PATH_MAX], *p;
47         int ret;
48
49         char *sysfs_dev = mprintf("/sys/dev/block/%u:%u",
50                                   major(dev), minor(dev));
51         ret = readlink(sysfs_dev, link, sizeof(link));
52         free(sysfs_dev);
53
54         if (ret < 0 || ret >= sizeof(link))
55                 die("readlink error while looking up block device: %m");
56
57         link[ret] = '\0';
58
59         p = strrchr(link, '/');
60         if (!p)
61                 die("error looking up device name");
62         p++;
63
64         return mprintf("/dev/%s", p);
65 }
66
67 static bool path_is_fs_root(const char *path)
68 {
69         char *line = NULL, *p, *mount;
70         size_t n = 0;
71         FILE *f;
72         bool ret = true;
73
74         f = fopen("/proc/self/mountinfo", "r");
75         if (!f)
76                 die("Error getting mount information");
77
78         while (getline(&line, &n, f) != -1) {
79                 p = line;
80
81                 strsep(&p, " "); /* mount id */
82                 strsep(&p, " "); /* parent id */
83                 strsep(&p, " "); /* dev */
84                 strsep(&p, " "); /* root */
85                 mount = strsep(&p, " ");
86                 strsep(&p, " ");
87
88                 if (mount && !strcmp(path, mount))
89                         goto found;
90         }
91
92         ret = false;
93 found:
94         fclose(f);
95         free(line);
96         return ret;
97 }
98
99 static void mark_unreserved_space(struct bch_fs *c, ranges extents)
100 {
101         struct bch_dev *ca = c->devs[0];
102         struct hole_iter iter;
103         struct range i;
104
105         for_each_hole(iter, extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i) {
106                 u64 b;
107
108                 if (i.start == i.end)
109                         return;
110
111                 b = sector_to_bucket(ca, i.start >> 9);
112                 do {
113                         set_bit(b, ca->buckets_nouse);
114                         b++;
115                 } while (bucket_to_sector(ca, b) << 9 < i.end);
116         }
117 }
118
119 static void update_inode(struct bch_fs *c,
120                          struct bch_inode_unpacked *inode)
121 {
122         struct bkey_inode_buf packed;
123         int ret;
124
125         bch2_inode_pack(c, &packed, inode);
126         ret = bch2_btree_insert(c, BTREE_ID_inodes, &packed.inode.k_i,
127                                 NULL, NULL, 0);
128         if (ret)
129                 die("error updating inode: %s", strerror(-ret));
130 }
131
132 static void create_link(struct bch_fs *c,
133                         struct bch_inode_unpacked *parent,
134                         const char *name, u64 inum, mode_t mode)
135 {
136         struct qstr qstr = QSTR(name);
137         struct bch_inode_unpacked parent_u;
138         struct bch_inode_unpacked inode;
139
140         int ret = bch2_trans_do(c, NULL, NULL, 0,
141                 bch2_link_trans(&trans,
142                                 (subvol_inum) { 1, parent->bi_inum }, &parent_u,
143                                 (subvol_inum) { 1, inum }, &inode, &qstr));
144         if (ret)
145                 die("error creating hardlink: %s", strerror(-ret));
146 }
147
148 static struct bch_inode_unpacked create_file(struct bch_fs *c,
149                                              struct bch_inode_unpacked *parent,
150                                              const char *name,
151                                              uid_t uid, gid_t gid,
152                                              mode_t mode, dev_t rdev)
153 {
154         struct qstr qstr = QSTR(name);
155         struct bch_inode_unpacked new_inode;
156
157         int ret = bch2_trans_do(c, NULL, NULL, 0,
158                 bch2_create_trans(&trans,
159                                   (subvol_inum) { 1, parent->bi_inum }, parent,
160                                   &new_inode, &qstr,
161                                   uid, gid, mode, rdev, NULL, NULL,
162                                   (subvol_inum) {}, 0));
163         if (ret)
164                 die("error creating file: %s", strerror(-ret));
165
166         return new_inode;
167 }
168
169 #define for_each_xattr_handler(handlers, handler)               \
170         if (handlers)                                           \
171                 for ((handler) = *(handlers)++;                 \
172                         (handler) != NULL;                      \
173                         (handler) = *(handlers)++)
174
175 static const struct xattr_handler *xattr_resolve_name(char **name)
176 {
177         const struct xattr_handler **handlers = bch2_xattr_handlers;
178         const struct xattr_handler *handler;
179
180         for_each_xattr_handler(handlers, handler) {
181                 char *n;
182
183                 n = strcmp_prefix(*name, xattr_prefix(handler));
184                 if (n) {
185                         if (!handler->prefix ^ !*n) {
186                                 if (*n)
187                                         continue;
188                                 return ERR_PTR(-EINVAL);
189                         }
190                         *name = n;
191                         return handler;
192                 }
193         }
194         return ERR_PTR(-EOPNOTSUPP);
195 }
196
197 static void copy_times(struct bch_fs *c, struct bch_inode_unpacked *dst,
198                        struct stat *src)
199 {
200         dst->bi_atime = timespec_to_bch2_time(c, src->st_atim);
201         dst->bi_mtime = timespec_to_bch2_time(c, src->st_mtim);
202         dst->bi_ctime = timespec_to_bch2_time(c, src->st_ctim);
203 }
204
205 static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
206                         char *src)
207 {
208         struct bch_hash_info hash_info = bch2_hash_info_init(c, dst);
209
210         char attrs[XATTR_LIST_MAX];
211         ssize_t attrs_size = llistxattr(src, attrs, sizeof(attrs));
212         if (attrs_size < 0)
213                 die("listxattr error: %m");
214
215         char *next, *attr;
216         for (attr = attrs;
217              attr < attrs + attrs_size;
218              attr = next) {
219                 next = attr + strlen(attr) + 1;
220
221                 char val[XATTR_SIZE_MAX];
222                 ssize_t val_size = lgetxattr(src, attr, val, sizeof(val));
223
224                 if (val_size < 0)
225                         die("error getting xattr val: %m");
226
227                 const struct xattr_handler *h = xattr_resolve_name(&attr);
228
229                 int ret = bch2_trans_do(c, NULL, NULL, 0,
230                                 bch2_xattr_set(&trans,
231                                                (subvol_inum) { 1, dst->bi_inum },
232                                                &hash_info, attr,
233                                                val, val_size, h->flags, 0));
234                 if (ret < 0)
235                         die("error creating xattr: %s", strerror(-ret));
236         }
237 }
238
239 static char buf[1 << 20] __aligned(PAGE_SIZE);
240
241 static void write_data(struct bch_fs *c,
242                        struct bch_inode_unpacked *dst_inode,
243                        u64 dst_offset, void *buf, size_t len)
244 {
245         struct {
246                 struct bch_write_op op;
247                 struct bio_vec bv[sizeof(buf) / PAGE_SIZE];
248         } o;
249         struct closure cl;
250
251         BUG_ON(dst_offset       & (block_bytes(c) - 1));
252         BUG_ON(len              & (block_bytes(c) - 1));
253
254         closure_init_stack(&cl);
255
256         bio_init(&o.op.wbio.bio, o.bv, ARRAY_SIZE(o.bv));
257         bch2_bio_map(&o.op.wbio.bio, buf, len);
258
259         bch2_write_op_init(&o.op, c, bch2_opts_to_inode_opts(c->opts));
260         o.op.write_point        = writepoint_hashed(0);
261         o.op.nr_replicas        = 1;
262         o.op.pos                = POS(dst_inode->bi_inum, dst_offset >> 9);
263
264         int ret = bch2_disk_reservation_get(c, &o.op.res, len >> 9,
265                                             c->opts.data_replicas, 0);
266         if (ret)
267                 die("error reserving space in new filesystem: %s", strerror(-ret));
268
269         closure_call(&o.op.cl, bch2_write, NULL, &cl);
270         closure_sync(&cl);
271
272         dst_inode->bi_sectors += len >> 9;
273 }
274
275 static void copy_data(struct bch_fs *c,
276                       struct bch_inode_unpacked *dst_inode,
277                       int src_fd, u64 start, u64 end)
278 {
279         while (start < end) {
280                 unsigned len = min_t(u64, end - start, sizeof(buf));
281                 unsigned pad = round_up(len, block_bytes(c)) - len;
282
283                 xpread(src_fd, buf, len, start);
284                 memset(buf + len, 0, pad);
285
286                 write_data(c, dst_inode, start, buf, len + pad);
287                 start += len;
288         }
289 }
290
291 static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
292                       u64 logical, u64 physical, u64 length)
293 {
294         struct bch_dev *ca = c->devs[0];
295
296         BUG_ON(logical  & (block_bytes(c) - 1));
297         BUG_ON(physical & (block_bytes(c) - 1));
298         BUG_ON(length   & (block_bytes(c) - 1));
299
300         logical         >>= 9;
301         physical        >>= 9;
302         length          >>= 9;
303
304         BUG_ON(physical + length > bucket_to_sector(ca, ca->mi.nbuckets));
305
306         while (length) {
307                 struct bkey_i_extent *e;
308                 __BKEY_PADDED(k, BKEY_EXTENT_VAL_U64s_MAX) k;
309                 u64 b = sector_to_bucket(ca, physical);
310                 struct disk_reservation res;
311                 unsigned sectors;
312                 int ret;
313
314                 sectors = min(ca->mi.bucket_size -
315                               (physical & (ca->mi.bucket_size - 1)),
316                               length);
317
318                 e = bkey_extent_init(&k.k);
319                 e->k.p.inode    = dst->bi_inum;
320                 e->k.p.offset   = logical + sectors;
321                 e->k.size       = sectors;
322                 bch2_bkey_append_ptr(&e->k_i, (struct bch_extent_ptr) {
323                                         .offset = physical,
324                                         .dev = 0,
325                                         .gen = bucket(ca, b)->mark.gen,
326                                   });
327
328                 ret = bch2_disk_reservation_get(c, &res, sectors, 1,
329                                                 BCH_DISK_RESERVATION_NOFAIL);
330                 if (ret)
331                         die("error reserving space in new filesystem: %s",
332                             strerror(-ret));
333
334                 bch2_mark_bkey_replicas(c, extent_i_to_s_c(e).s_c);
335
336                 ret = bch2_btree_insert(c, BTREE_ID_extents, &e->k_i,
337                                         &res, NULL, 0);
338                 if (ret)
339                         die("btree insert error %s", strerror(-ret));
340
341                 bch2_disk_reservation_put(c, &res);
342
343                 dst->bi_sectors += sectors;
344                 logical         += sectors;
345                 physical        += sectors;
346                 length          -= sectors;
347         }
348 }
349
350 static void copy_link(struct bch_fs *c, struct bch_inode_unpacked *dst,
351                       char *src)
352 {
353         ssize_t ret = readlink(src, buf, sizeof(buf));
354         if (ret < 0)
355                 die("readlink error: %m");
356
357         write_data(c, dst, 0, buf, round_up(ret, block_bytes(c)));
358 }
359
360 static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
361                       int src_fd, u64 src_size,
362                       char *src_path, ranges *extents)
363 {
364         struct fiemap_iter iter;
365         struct fiemap_extent e;
366
367         fiemap_for_each(src_fd, iter, e)
368                 if (e.fe_flags & FIEMAP_EXTENT_UNKNOWN) {
369                         fsync(src_fd);
370                         break;
371                 }
372
373         fiemap_for_each(src_fd, iter, e) {
374                 if ((e.fe_logical       & (block_bytes(c) - 1)) ||
375                     (e.fe_length        & (block_bytes(c) - 1)))
376                         die("Unaligned extent in %s - can't handle", src_path);
377
378                 if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN|
379                                   FIEMAP_EXTENT_ENCODED|
380                                   FIEMAP_EXTENT_NOT_ALIGNED|
381                                   FIEMAP_EXTENT_DATA_INLINE)) {
382                         copy_data(c, dst, src_fd, e.fe_logical,
383                                   min(src_size - e.fe_logical,
384                                       e.fe_length));
385                         continue;
386                 }
387
388                 /*
389                  * if the data is below 1 MB, copy it so it doesn't conflict
390                  * with bcachefs's potentially larger superblock:
391                  */
392                 if (e.fe_physical < 1 << 20) {
393                         copy_data(c, dst, src_fd, e.fe_logical,
394                                   min(src_size - e.fe_logical,
395                                       e.fe_length));
396                         continue;
397                 }
398
399                 if ((e.fe_physical      & (block_bytes(c) - 1)))
400                         die("Unaligned extent in %s - can't handle", src_path);
401
402                 range_add(extents, e.fe_physical, e.fe_length);
403                 link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
404         }
405 }
406
407 struct copy_fs_state {
408         u64                     bcachefs_inum;
409         dev_t                   dev;
410
411         GENRADIX(u64)           hardlinks;
412         ranges                  extents;
413 };
414
415 static void copy_dir(struct copy_fs_state *s,
416                      struct bch_fs *c,
417                      struct bch_inode_unpacked *dst,
418                      int src_fd, const char *src_path)
419 {
420         DIR *dir = fdopendir(src_fd);
421         struct dirent *d;
422
423         while ((errno = 0), (d = readdir(dir))) {
424                 struct bch_inode_unpacked inode;
425                 int fd;
426
427                 if (fchdir(src_fd))
428                         die("chdir error: %m");
429
430                 struct stat stat =
431                         xfstatat(src_fd, d->d_name, AT_SYMLINK_NOFOLLOW);
432
433                 if (!strcmp(d->d_name, ".") ||
434                     !strcmp(d->d_name, "..") ||
435                     stat.st_ino == s->bcachefs_inum)
436                         continue;
437
438                 char *child_path = mprintf("%s/%s", src_path, d->d_name);
439
440                 if (stat.st_dev != s->dev)
441                         die("%s does not have correct st_dev!", child_path);
442
443                 u64 *dst_inum = S_ISREG(stat.st_mode)
444                         ? genradix_ptr_alloc(&s->hardlinks, stat.st_ino, GFP_KERNEL)
445                         : NULL;
446
447                 if (dst_inum && *dst_inum) {
448                         create_link(c, dst, d->d_name, *dst_inum, S_IFREG);
449                         goto next;
450                 }
451
452                 inode = create_file(c, dst, d->d_name,
453                                     stat.st_uid, stat.st_gid,
454                                     stat.st_mode, stat.st_rdev);
455
456                 if (dst_inum)
457                         *dst_inum = inode.bi_inum;
458
459                 copy_times(c, &inode, &stat);
460                 copy_xattrs(c, &inode, d->d_name);
461
462                 /* copy xattrs */
463
464                 switch (mode_to_type(stat.st_mode)) {
465                 case DT_DIR:
466                         fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
467                         copy_dir(s, c, &inode, fd, child_path);
468                         close(fd);
469                         break;
470                 case DT_REG:
471                         inode.bi_size = stat.st_size;
472
473                         fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
474                         copy_file(c, &inode, fd, stat.st_size,
475                                   child_path, &s->extents);
476                         close(fd);
477                         break;
478                 case DT_LNK:
479                         inode.bi_size = stat.st_size;
480
481                         copy_link(c, &inode, d->d_name);
482                         break;
483                 case DT_FIFO:
484                 case DT_CHR:
485                 case DT_BLK:
486                 case DT_SOCK:
487                 case DT_WHT:
488                         /* nothing else to copy for these: */
489                         break;
490                 default:
491                         BUG();
492                 }
493
494                 update_inode(c, &inode);
495 next:
496                 free(child_path);
497         }
498
499         if (errno)
500                 die("readdir error: %m");
501 }
502
503 static ranges reserve_new_fs_space(const char *file_path, unsigned block_size,
504                                    u64 size, u64 *bcachefs_inum, dev_t dev,
505                                    bool force)
506 {
507         int fd = force
508                 ? open(file_path, O_RDWR|O_CREAT, 0600)
509                 : open(file_path, O_RDWR|O_CREAT|O_EXCL, 0600);
510         if (fd < 0)
511                 die("Error creating %s for bcachefs metadata: %m",
512                     file_path);
513
514         struct stat statbuf = xfstat(fd);
515
516         if (statbuf.st_dev != dev)
517                 die("bcachefs file has incorrect device");
518
519         *bcachefs_inum = statbuf.st_ino;
520
521         if (fallocate(fd, 0, 0, size))
522                 die("Error reserving space for bcachefs metadata: %m");
523
524         fsync(fd);
525
526         struct fiemap_iter iter;
527         struct fiemap_extent e;
528         ranges extents = { NULL };
529
530         fiemap_for_each(fd, iter, e) {
531                 if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN|
532                                   FIEMAP_EXTENT_ENCODED|
533                                   FIEMAP_EXTENT_NOT_ALIGNED|
534                                   FIEMAP_EXTENT_DATA_INLINE))
535                         die("Unable to continue: metadata file not fully mapped");
536
537                 if ((e.fe_physical      & (block_size - 1)) ||
538                     (e.fe_length        & (block_size - 1)))
539                         die("Unable to continue: unaligned extents in metadata file");
540
541                 range_add(&extents, e.fe_physical, e.fe_length);
542         }
543         close(fd);
544
545         ranges_sort_merge(&extents);
546         return extents;
547 }
548
549 static void reserve_old_fs_space(struct bch_fs *c,
550                                  struct bch_inode_unpacked *root_inode,
551                                  ranges *extents)
552 {
553         struct bch_dev *ca = c->devs[0];
554         struct bch_inode_unpacked dst;
555         struct hole_iter iter;
556         struct range i;
557
558         dst = create_file(c, root_inode, "old_migrated_filesystem",
559                           0, 0, S_IFREG|0400, 0);
560         dst.bi_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
561
562         ranges_sort_merge(extents);
563
564         for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i)
565                 link_data(c, &dst, i.start, i.start, i.end - i.start);
566
567         update_inode(c, &dst);
568 }
569
570 static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
571                     u64 bcachefs_inum, ranges *extents)
572 {
573         syncfs(src_fd);
574
575         struct bch_inode_unpacked root_inode;
576         int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO },
577                                           &root_inode);
578         if (ret)
579                 die("error looking up root directory: %s", strerror(-ret));
580
581         if (fchdir(src_fd))
582                 die("chdir error: %m");
583
584         struct stat stat = xfstat(src_fd);
585         copy_times(c, &root_inode, &stat);
586         copy_xattrs(c, &root_inode, ".");
587
588         struct copy_fs_state s = {
589                 .bcachefs_inum  = bcachefs_inum,
590                 .dev            = stat.st_dev,
591                 .extents        = *extents,
592         };
593
594         /* now, copy: */
595         copy_dir(&s, c, &root_inode, src_fd, src_path);
596
597         reserve_old_fs_space(c, &root_inode, &s.extents);
598
599         update_inode(c, &root_inode);
600
601         darray_free(s.extents);
602         genradix_free(&s.hardlinks);
603
604         bch2_alloc_write(c, false);
605 }
606
607 static void find_superblock_space(ranges extents,
608                                   struct format_opts opts,
609                                   struct dev_opts *dev)
610 {
611         struct range *i;
612
613         darray_foreach(i, extents) {
614                 u64 start = round_up(max(256ULL << 10, i->start),
615                                      dev->bucket_size << 9);
616                 u64 end = round_down(i->end,
617                                      dev->bucket_size << 9);
618
619                 /* Need space for two superblocks: */
620                 if (start + (opts.superblock_size << 9) * 2 <= end) {
621                         dev->sb_offset  = start >> 9;
622                         dev->sb_end     = dev->sb_offset + opts.superblock_size * 2;
623                         return;
624                 }
625         }
626
627         die("Couldn't find a valid location for superblock");
628 }
629
630 static void migrate_usage(void)
631 {
632         puts("bcachefs migrate - migrate an existing filesystem to bcachefs\n"
633              "Usage: bcachefs migrate [OPTION]...\n"
634              "\n"
635              "Options:\n"
636              "  -f fs                  Root of filesystem to migrate(s)\n"
637              "      --encrypted        Enable whole filesystem encryption (chacha20/poly1305)\n"
638              "      --no_passphrase    Don't encrypt master encryption key\n"
639              "  -F                     Force, even if metadata file already exists\n"
640              "  -h                     Display this help and exit\n"
641              "Report bugs to <linux-bcache@vger.kernel.org>");
642 }
643
644 static const struct option migrate_opts[] = {
645         { "encrypted",          no_argument, NULL, 'e' },
646         { "no_passphrase",      no_argument, NULL, 'p' },
647         { NULL }
648 };
649
650 static int migrate_fs(const char                *fs_path,
651                       struct bch_opt_strs       fs_opt_strs,
652                       struct bch_opts           fs_opts,
653                       struct format_opts        format_opts,
654                       bool force)
655 {
656         if (!path_is_fs_root(fs_path))
657                 die("%s is not a filysestem root", fs_path);
658
659         int fs_fd = xopen(fs_path, O_RDONLY|O_NOATIME);
660         struct stat stat = xfstat(fs_fd);
661
662         if (!S_ISDIR(stat.st_mode))
663                 die("%s is not a directory", fs_path);
664
665         struct dev_opts dev = dev_opts_default();
666
667         dev.path = dev_t_to_path(stat.st_dev);
668         dev.fd = xopen(dev.path, O_RDWR);
669
670         opt_set(fs_opts, block_size, get_blocksize(dev.path, dev.fd));
671
672         char *file_path = mprintf("%s/bcachefs", fs_path);
673         printf("Creating new filesystem on %s in space reserved at %s\n",
674                dev.path, file_path);
675
676         bch2_pick_bucket_size(fs_opts, &dev);
677
678         u64 bcachefs_inum;
679         ranges extents = reserve_new_fs_space(file_path,
680                                 fs_opts.block_size << 9,
681                                 get_size(dev.path, dev.fd) / 5,
682                                 &bcachefs_inum, stat.st_dev, force);
683
684         find_superblock_space(extents, format_opts, &dev);
685
686         struct bch_sb *sb = bch2_format(fs_opt_strs,
687                                         fs_opts,format_opts, &dev, 1);
688         u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
689
690         if (format_opts.passphrase)
691                 bch2_add_key(sb, format_opts.passphrase);
692
693         free(sb);
694
695         struct bch_opts opts = bch2_opts_empty();
696         struct bch_fs *c = NULL;
697         char *path[1] = { dev.path };
698
699         opt_set(opts, sb,       sb_offset);
700         opt_set(opts, nostart,  true);
701         opt_set(opts, noexcl,   true);
702
703         c = bch2_fs_open(path, 1, opts);
704         if (IS_ERR(c))
705                 die("Error opening new filesystem: %s", strerror(-PTR_ERR(c)));
706
707         mark_unreserved_space(c, extents);
708
709         int ret = bch2_fs_start(c);
710         if (ret)
711                 die("Error starting new filesystem: %s", strerror(-ret));
712
713         copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents);
714
715         bch2_fs_stop(c);
716
717         printf("Migrate complete, running fsck:\n");
718         opt_set(opts, nostart,  false);
719         opt_set(opts, nochanges, true);
720
721         c = bch2_fs_open(path, 1, opts);
722         if (IS_ERR(c))
723                 die("Error opening new filesystem: %s", strerror(-PTR_ERR(c)));
724
725         bch2_fs_stop(c);
726         printf("fsck complete\n");
727
728         printf("To mount the new filesystem, run\n"
729                "  mount -t bcachefs -o sb=%llu %s dir\n"
730                "\n"
731                "After verifying that the new filesystem is correct, to create a\n"
732                "superblock at the default offset and finish the migration run\n"
733                "  bcachefs migrate-superblock -d %s -o %llu\n"
734                "\n"
735                "The new filesystem will have a file at /old_migrated_filestem\n"
736                "referencing all disk space that might be used by the existing\n"
737                "filesystem. That file can be deleted once the old filesystem is\n"
738                "no longer needed (and should be deleted prior to running\n"
739                "bcachefs migrate-superblock)\n",
740                sb_offset, dev.path, dev.path, sb_offset);
741         return 0;
742 }
743
744 int cmd_migrate(int argc, char *argv[])
745 {
746         struct format_opts format_opts = format_opts_default();
747         char *fs_path = NULL;
748         bool no_passphrase = false, force = false;
749         int opt;
750
751         struct bch_opt_strs fs_opt_strs =
752                 bch2_cmdline_opts_get(&argc, argv, OPT_FORMAT);
753         struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs);
754
755         while ((opt = getopt_long(argc, argv, "f:Fh",
756                                   migrate_opts, NULL)) != -1)
757                 switch (opt) {
758                 case 'f':
759                         fs_path = optarg;
760                         break;
761                 case 'e':
762                         format_opts.encrypted = true;
763                         break;
764                 case 'p':
765                         no_passphrase = true;
766                         break;
767                 case 'F':
768                         force = true;
769                         break;
770                 case 'h':
771                         migrate_usage();
772                         exit(EXIT_SUCCESS);
773                 }
774
775         if (!fs_path)
776                 die("Please specify a filesystem to migrate");
777
778         if (format_opts.encrypted && !no_passphrase)
779                 format_opts.passphrase = read_passphrase_twice("Enter passphrase: ");
780
781         int ret = migrate_fs(fs_path,
782                              fs_opt_strs,
783                              fs_opts,
784                              format_opts, force);
785         bch2_opt_strs_free(&fs_opt_strs);
786         return ret;
787 }
788
789 static void migrate_superblock_usage(void)
790 {
791         puts("bcachefs migrate-superblock - create default superblock after migrating\n"
792              "Usage: bcachefs migrate-superblock [OPTION]...\n"
793              "\n"
794              "Options:\n"
795              "  -d device     Device to create superblock for\n"
796              "  -o offset     Offset of existing superblock\n"
797              "  -h            Display this help and exit\n"
798              "Report bugs to <linux-bcache@vger.kernel.org>");
799 }
800
801 int cmd_migrate_superblock(int argc, char *argv[])
802 {
803         char *dev = NULL;
804         u64 offset = 0;
805         int opt, ret;
806
807         while ((opt = getopt(argc, argv, "d:o:h")) != -1)
808                 switch (opt) {
809                         case 'd':
810                                 dev = optarg;
811                                 break;
812                         case 'o':
813                                 ret = kstrtou64(optarg, 10, &offset);
814                                 if (ret)
815                                         die("Invalid offset");
816                                 break;
817                         case 'h':
818                                 migrate_superblock_usage();
819                                 exit(EXIT_SUCCESS);
820                 }
821
822         if (!dev)
823                 die("Please specify a device");
824
825         if (!offset)
826                 die("Please specify offset of existing superblock");
827
828         int fd = xopen(dev, O_RDWR);
829         struct bch_sb *sb = __bch2_super_read(fd, offset);
830
831         if (sb->layout.nr_superblocks >= ARRAY_SIZE(sb->layout.sb_offset))
832                 die("Can't add superblock: no space left in superblock layout");
833
834         unsigned i;
835         for (i = 0; i < sb->layout.nr_superblocks; i++)
836                 if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR)
837                         die("Superblock layout already has default superblock");
838
839         memmove(&sb->layout.sb_offset[1],
840                 &sb->layout.sb_offset[0],
841                 sb->layout.nr_superblocks * sizeof(u64));
842         sb->layout.nr_superblocks++;
843
844         sb->layout.sb_offset[0] = cpu_to_le64(BCH_SB_SECTOR);
845
846         bch2_super_write(fd, sb);
847         close(fd);
848
849         return 0;
850 }