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