]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_migrate.c
bcachefs-in-userspace 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      & (block_bytes(c) - 1)))
394                         die("Unaligned extent in %s - can't handle", src_path);
395
396                 range_add(extents, e.fe_physical, e.fe_length);
397                 link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
398         }
399 }
400
401 struct copy_fs_state {
402         u64                     bcachefs_inum;
403         dev_t                   dev;
404
405         GENRADIX(u64)           hardlinks;
406         ranges                  extents;
407 };
408
409 static void copy_dir(struct copy_fs_state *s,
410                      struct bch_fs *c,
411                      struct bch_inode_unpacked *dst,
412                      int src_fd, const char *src_path)
413 {
414         DIR *dir = fdopendir(src_fd);
415         struct dirent *d;
416
417         while ((errno = 0), (d = readdir(dir))) {
418                 struct bch_inode_unpacked inode;
419                 int fd;
420
421                 if (fchdir(src_fd))
422                         die("chdir error: %s", strerror(errno));
423
424                 struct stat stat =
425                         xfstatat(src_fd, d->d_name, AT_SYMLINK_NOFOLLOW);
426
427                 if (!strcmp(d->d_name, ".") ||
428                     !strcmp(d->d_name, "..") ||
429                     stat.st_ino == s->bcachefs_inum)
430                         continue;
431
432                 char *child_path = mprintf("%s/%s", src_path, d->d_name);
433
434                 if (stat.st_dev != s->dev)
435                         die("%s does not have correct st_dev!", child_path);
436
437                 u64 *dst_inum = S_ISREG(stat.st_mode)
438                         ? genradix_ptr_alloc(&s->hardlinks, stat.st_ino, GFP_KERNEL)
439                         : NULL;
440
441                 if (dst_inum && *dst_inum) {
442                         create_link(c, dst, d->d_name, *dst_inum, S_IFREG);
443                         goto next;
444                 }
445
446                 inode = create_file(c, dst, d->d_name,
447                                     stat.st_uid, stat.st_gid,
448                                     stat.st_mode, stat.st_rdev);
449
450                 if (dst_inum)
451                         *dst_inum = inode.inum;
452
453                 copy_times(c, &inode, &stat);
454                 copy_xattrs(c, &inode, d->d_name);
455
456                 /* copy xattrs */
457
458                 switch (mode_to_type(stat.st_mode)) {
459                 case DT_DIR:
460                         fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
461                         copy_dir(s, c, &inode, fd, child_path);
462                         close(fd);
463                         break;
464                 case DT_REG:
465                         inode.i_size = stat.st_size;
466
467                         fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
468                         copy_file(c, &inode, fd, child_path, &s->extents);
469                         close(fd);
470                         break;
471                 case DT_LNK:
472                         inode.i_size = stat.st_size;
473
474                         copy_link(c, &inode, d->d_name);
475                         break;
476                 case DT_FIFO:
477                 case DT_CHR:
478                 case DT_BLK:
479                 case DT_SOCK:
480                 case DT_WHT:
481                         /* nothing else to copy for these: */
482                         break;
483                 default:
484                         BUG();
485                 }
486
487                 update_inode(c, &inode);
488 next:
489                 free(child_path);
490         }
491
492         if (errno)
493                 die("readdir error: %s", strerror(errno));
494 }
495
496 static ranges reserve_new_fs_space(const char *file_path, unsigned block_size,
497                                    u64 size, u64 *bcachefs_inum, dev_t dev,
498                                    bool force)
499 {
500         int fd = force
501                 ? open(file_path, O_RDWR|O_CREAT, 0600)
502                 : open(file_path, O_RDWR|O_CREAT|O_EXCL, 0600);
503         if (fd < 0)
504                 die("Error creating %s for bcachefs metadata: %s",
505                     file_path, strerror(errno));
506
507         struct stat statbuf = xfstat(fd);
508
509         if (statbuf.st_dev != dev)
510                 die("bcachefs file has incorrect device");
511
512         *bcachefs_inum = statbuf.st_ino;
513
514         if (fallocate(fd, 0, 0, size))
515                 die("Error reserving space for bcachefs metadata: %s",
516                     strerror(errno));
517
518         fsync(fd);
519
520         struct fiemap_iter iter;
521         struct fiemap_extent e;
522         ranges extents = { NULL };
523
524         fiemap_for_each(fd, iter, e) {
525                 if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN|
526                                   FIEMAP_EXTENT_ENCODED|
527                                   FIEMAP_EXTENT_NOT_ALIGNED|
528                                   FIEMAP_EXTENT_DATA_INLINE))
529                         die("Unable to continue: metadata file not fully mapped");
530
531                 if ((e.fe_physical      & (block_size - 1)) ||
532                     (e.fe_length        & (block_size - 1)))
533                         die("Unable to continue: unaligned extents in metadata file");
534
535                 range_add(&extents, e.fe_physical, e.fe_length);
536         }
537         close(fd);
538
539         ranges_sort_merge(&extents);
540         return extents;
541 }
542
543 static void reserve_old_fs_space(struct bch_fs *c,
544                                  struct bch_inode_unpacked *root_inode,
545                                  ranges *extents)
546 {
547         struct bch_dev *ca = c->devs[0];
548         struct bch_inode_unpacked dst;
549         struct hole_iter iter;
550         struct range i;
551
552         dst = create_file(c, root_inode, "old_migrated_filesystem",
553                           0, 0, S_IFREG|0400, 0);
554         dst.i_size = bucket_to_sector(ca, ca->mi.nbuckets) << 9;
555
556         ranges_sort_merge(extents);
557
558         for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i)
559                 link_data(c, &dst, i.start, i.start, i.end - i.start);
560
561         update_inode(c, &dst);
562 }
563
564 static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
565                     u64 bcachefs_inum, ranges *extents)
566 {
567         syncfs(src_fd);
568
569         struct bch_inode_unpacked root_inode;
570         int ret = bch2_inode_find_by_inum(c, BCACHE_ROOT_INO, &root_inode);
571         if (ret)
572                 die("error looking up root directory: %s", strerror(-ret));
573
574         if (fchdir(src_fd))
575                 die("chdir error: %s", strerror(errno));
576
577         struct stat stat = xfstat(src_fd);
578         copy_times(c, &root_inode, &stat);
579         copy_xattrs(c, &root_inode, ".");
580
581         struct copy_fs_state s = {
582                 .bcachefs_inum  = bcachefs_inum,
583                 .dev            = stat.st_dev,
584                 .extents        = *extents,
585         };
586
587         /* now, copy: */
588         copy_dir(&s, c, &root_inode, src_fd, src_path);
589
590         reserve_old_fs_space(c, &root_inode, &s.extents);
591
592         update_inode(c, &root_inode);
593
594         darray_free(s.extents);
595         genradix_free(&s.hardlinks);
596 }
597
598 static void find_superblock_space(ranges extents, struct dev_opts *dev)
599 {
600         struct range *i;
601         darray_foreach(i, extents) {
602                 u64 offset = max(256ULL << 10, i->start);
603
604                 if (offset + (128 << 10) <= i->end) {
605                         dev->sb_offset  = offset >> 9;
606                         dev->sb_end     = dev->sb_offset + 256;
607                         return;
608                 }
609         }
610
611         die("Couldn't find a valid location for superblock");
612 }
613
614 static void migrate_usage(void)
615 {
616         puts("bcachefs migrate - migrate an existing filesystem to bcachefs\n"
617              "Usage: bcachefs migrate [OPTION]...\n"
618              "\n"
619              "Options:\n"
620              "  -f fs                  Root of filesystem to migrate(s)\n"
621              "      --encrypted        Enable whole filesystem encryption (chacha20/poly1305)\n"
622              "      --no_passphrase    Don't encrypt master encryption key\n"
623              "  -F                     Force, even if metadata file already exists\n"
624              "  -h                     Display this help and exit\n"
625              "Report bugs to <linux-bcache@vger.kernel.org>");
626 }
627
628 static const struct option migrate_opts[] = {
629         { "encrypted",          no_argument, NULL, 'e' },
630         { "no_passphrase",      no_argument, NULL, 'p' },
631         { NULL }
632 };
633
634 int cmd_migrate(int argc, char *argv[])
635 {
636         struct format_opts format_opts = format_opts_default();
637         char *fs_path = NULL;
638         unsigned block_size;
639         bool no_passphrase = false, force = false;
640         int opt;
641
642         while ((opt = getopt_long(argc, argv, "f:Fh",
643                                   migrate_opts, NULL)) != -1)
644                 switch (opt) {
645                 case 'f':
646                         fs_path = optarg;
647                         break;
648                 case 'e':
649                         format_opts.encrypted = true;
650                         break;
651                 case 'p':
652                         no_passphrase = true;
653                         break;
654                 case 'F':
655                         force = true;
656                         break;
657                 case 'h':
658                         migrate_usage();
659                         exit(EXIT_SUCCESS);
660                 }
661
662         if (!fs_path)
663                 die("Please specify a filesytem to migrate");
664
665         if (!path_is_fs_root(fs_path))
666                 die("%s is not a filysestem root", fs_path);
667
668         int fs_fd = xopen(fs_path, O_RDONLY|O_NOATIME);
669         struct stat stat = xfstat(fs_fd);
670
671         if (!S_ISDIR(stat.st_mode))
672                 die("%s is not a directory", fs_path);
673
674         struct dev_opts dev = { 0 };
675
676         dev.path = dev_t_to_path(stat.st_dev);
677         dev.fd = xopen(dev.path, O_RDWR);
678
679         block_size = min_t(unsigned, stat.st_blksize,
680                            get_blocksize(dev.path, dev.fd) << 9);
681
682         BUG_ON(!is_power_of_2(block_size) || block_size < 512);
683         format_opts.block_size = block_size >> 9;
684
685         u64 bcachefs_inum;
686         char *file_path = mprintf("%s/bcachefs", fs_path);
687
688         ranges extents = reserve_new_fs_space(file_path,
689                                 block_size, get_size(dev.path, dev.fd) / 5,
690                                 &bcachefs_inum, stat.st_dev, force);
691
692         find_superblock_space(extents, &dev);
693
694         if (format_opts.encrypted && !no_passphrase) {
695                 format_opts.passphrase = read_passphrase("Enter passphrase: ");
696
697                 if (isatty(STDIN_FILENO)) {
698                         char *pass2 =
699                                 read_passphrase("Enter same passphrase again: ");
700
701                         if (strcmp(format_opts.passphrase, pass2)) {
702                                 memzero_explicit(format_opts.passphrase,
703                                                  strlen(format_opts.passphrase));
704                                 memzero_explicit(pass2, strlen(pass2));
705                                 die("Passphrases do not match");
706                         }
707
708                         memzero_explicit(pass2, strlen(pass2));
709                         free(pass2);
710                 }
711         }
712
713         struct bch_sb *sb = bcache_format(format_opts, &dev, 1);
714         u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
715
716         if (format_opts.passphrase)
717                 add_bcache_key(sb, format_opts.passphrase);
718
719         free(sb);
720
721         printf("Creating new filesystem on %s in space reserved at %s\n"
722                "To mount, run\n"
723                "  mount -t bcachefs -o sb=%llu %s dir\n"
724                "\n"
725                "After verifying that the new filesystem is correct, to create a\n"
726                "superblock at the default offset and finish the migration run\n"
727                "  bcachefs migrate_superblock -d %s -o %llu\n"
728                "\n"
729                "The new filesystem will have a file at /old_migrated_filestem\n"
730                "referencing all disk space that might be used by the existing\n"
731                "filesystem. That file can be deleted once the old filesystem is\n"
732                "no longer needed (and should be deleted prior to running\n"
733                "bcachefs migrate_superblock)\n",
734                dev.path, file_path, sb_offset, dev.path,
735                dev.path, sb_offset);
736
737         struct bch_opts opts = bch2_opts_empty();
738         struct bch_fs *c = NULL;
739         char *path[1] = { dev.path };
740         const char *err;
741
742         opts.sb         = sb_offset;
743         opts.nostart    = true;
744         opts.noexcl     = true;
745
746         err = bch2_fs_open(path, 1, opts, &c);
747         if (err)
748                 die("Error opening new filesystem: %s", err);
749
750         mark_unreserved_space(c, extents);
751
752         err = bch2_fs_start(c);
753         if (err)
754                 die("Error starting new filesystem: %s", err);
755
756         copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents);
757
758         bch2_fs_stop(c);
759
760         printf("Migrate complete, running fsck:\n");
761         opts.nostart    = false;
762         opts.nochanges  = true;
763
764         err = bch2_fs_open(path, 1, opts, &c);
765         if (err)
766                 die("Error opening new filesystem: %s", err);
767
768         bch2_fs_stop(c);
769         printf("fsck complete\n");
770         return 0;
771 }
772
773 static void migrate_superblock_usage(void)
774 {
775         puts("bcachefs migrate_superblock - create default superblock after migrating\n"
776              "Usage: bcachefs migrate_superblock [OPTION]...\n"
777              "\n"
778              "Options:\n"
779              "  -d device     Device to create superblock for\n"
780              "  -o offset     Offset of existing superblock\n"
781              "  -h            Display this help and exit\n"
782              "Report bugs to <linux-bcache@vger.kernel.org>");
783 }
784
785 int cmd_migrate_superblock(int argc, char *argv[])
786 {
787         char *dev = NULL;
788         u64 offset = 0;
789         int opt, ret;
790
791         while ((opt = getopt(argc, argv, "d:o:h")) != -1)
792                 switch (opt) {
793                         case 'd':
794                                 dev = optarg;
795                                 break;
796                         case 'o':
797                                 ret = kstrtou64(optarg, 10, &offset);
798                                 if (ret)
799                                         die("Invalid offset");
800                                 break;
801                         case 'h':
802                                 migrate_superblock_usage();
803                                 exit(EXIT_SUCCESS);
804                 }
805
806         if (!dev)
807                 die("Please specify a device");
808
809         if (!offset)
810                 die("Please specify offset of existing superblock");
811
812         int fd = xopen(dev, O_RDWR);
813         struct bch_sb *sb = __bcache_super_read(fd, offset);
814
815         if (sb->layout.nr_superblocks >= ARRAY_SIZE(sb->layout.sb_offset))
816                 die("Can't add superblock: no space left in superblock layout");
817
818         for (unsigned i = 0; i < sb->layout.nr_superblocks; i++)
819                 if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR)
820                         die("Superblock layout already has default superblock");
821
822         memmove(&sb->layout.sb_offset[1],
823                 &sb->layout.sb_offset[0],
824                 sb->layout.nr_superblocks * sizeof(u64));
825         sb->layout.nr_superblocks++;
826
827         sb->layout.sb_offset[0] = cpu_to_le64(BCH_SB_SECTOR);
828
829         bcache_super_write(fd, sb);
830         close(fd);
831
832         return 0;
833 }