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