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