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