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