X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_migrate.c;h=07fc145290034ae9eed9706d86caada62c116202;hb=89abdd87271e237141a9d4f44d531f7c53353b83;hp=e9594ab79bb869c2b16b986d7bf0368396b098d6;hpb=47bd483d27ec13418978b24ec5951661d564ba35;p=bcachefs-tools-debian diff --git a/cmd_migrate.c b/cmd_migrate.c index e9594ab..07fc145 100644 --- a/cmd_migrate.c +++ b/cmd_migrate.c @@ -30,14 +30,18 @@ #include "libbcachefs/btree_update.h" #include "libbcachefs/buckets.h" #include "libbcachefs/dirent.h" -#include "libbcachefs/fs.h" +#include "libbcachefs/errcode.h" +#include "libbcachefs/fs-common.h" #include "libbcachefs/inode.h" -#include "libbcachefs/io.h" +#include "libbcachefs/io_write.h" #include "libbcachefs/replicas.h" #include "libbcachefs/str_hash.h" #include "libbcachefs/super.h" #include "libbcachefs/xattr.h" +/* XXX cut and pasted from fsck.c */ +#define QSTR(n) { { { .len = strlen(n) } }, .name = n } + static char *dev_t_to_path(dev_t dev) { char link[PATH_MAX], *p; @@ -120,42 +124,27 @@ static void update_inode(struct bch_fs *c, int ret; bch2_inode_pack(&packed, inode); - ret = bch2_btree_insert(c, BTREE_ID_INODES, &packed.inode.k_i, - NULL, NULL, 0); - if (ret) - die("error creating file: %s", strerror(-ret)); -} - -static void create_dirent(struct bch_fs *c, - struct bch_inode_unpacked *parent, - const char *name, u64 inum, mode_t mode) -{ - struct bch_hash_info parent_hash_info = bch2_hash_info_init(c, parent); - struct qstr qname = { { { .len = strlen(name), } }, .name = name }; - - int ret = bch2_dirent_create(c, parent->bi_inum, &parent_hash_info, - mode_to_type(mode), &qname, - inum, NULL, BCH_HASH_SET_MUST_CREATE); + packed.inode.k.p.snapshot = U32_MAX; + ret = bch2_btree_insert(c, BTREE_ID_inodes, &packed.inode.k_i, + NULL, 0); if (ret) - die("error creating file: %s", strerror(-ret)); - - if (S_ISDIR(mode)) - parent->bi_nlink++; + die("error updating inode: %s", bch2_err_str(ret)); } static void create_link(struct bch_fs *c, struct bch_inode_unpacked *parent, const char *name, u64 inum, mode_t mode) { + struct qstr qstr = QSTR(name); + struct bch_inode_unpacked parent_u; struct bch_inode_unpacked inode; - int ret = bch2_inode_find_by_inum(c, inum, &inode); - if (ret) - die("error looking up hardlink: %s", strerror(-ret)); - - inode.bi_nlink++; - update_inode(c, &inode); - create_dirent(c, parent, name, inum, mode); + int ret = bch2_trans_do(c, NULL, NULL, 0, + bch2_link_trans(trans, + (subvol_inum) { 1, parent->bi_inum }, &parent_u, + (subvol_inum) { 1, inum }, &inode, &qstr)); + if (ret) + die("error creating hardlink: %s", bch2_err_str(ret)); } static struct bch_inode_unpacked create_file(struct bch_fs *c, @@ -164,17 +153,19 @@ static struct bch_inode_unpacked create_file(struct bch_fs *c, uid_t uid, gid_t gid, mode_t mode, dev_t rdev) { + struct qstr qstr = QSTR(name); struct bch_inode_unpacked new_inode; - int ret; - bch2_inode_init(c, &new_inode, uid, gid, mode, rdev, parent); + bch2_inode_init_early(c, &new_inode); - ret = bch2_inode_create(c, &new_inode, BLOCKDEV_INODE_MAX, 0, - &c->unused_inode_hint); + int ret = bch2_trans_do(c, NULL, NULL, 0, + bch2_create_trans(trans, + (subvol_inum) { 1, parent->bi_inum }, parent, + &new_inode, &qstr, + uid, gid, mode, rdev, NULL, NULL, + (subvol_inum) {}, 0)); if (ret) - die("error creating file: %s", strerror(-ret)); - - create_dirent(c, parent, name, new_inode.bi_inum, mode); + die("error creating %s: %s", name, bch2_err_str(ret)); return new_inode; } @@ -238,50 +229,55 @@ static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst, die("error getting xattr val: %m"); const struct xattr_handler *h = xattr_resolve_name(&attr); + struct bch_inode_unpacked inode_u; - int ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC, - bch2_xattr_set(&trans, dst->bi_inum, &hash_info, attr, + int ret = bch2_trans_do(c, NULL, NULL, 0, + bch2_xattr_set(trans, + (subvol_inum) { 1, dst->bi_inum }, + &inode_u, &hash_info, attr, val, val_size, h->flags, 0)); if (ret < 0) - die("error creating xattr: %s", strerror(-ret)); + die("error creating xattr: %s", bch2_err_str(ret)); } } -static char buf[1 << 20] __aligned(PAGE_SIZE); +#define WRITE_DATA_BUF (1 << 20) + +static char buf[WRITE_DATA_BUF] __aligned(PAGE_SIZE); static void write_data(struct bch_fs *c, struct bch_inode_unpacked *dst_inode, u64 dst_offset, void *buf, size_t len) { - struct { - struct bch_write_op op; - struct bio_vec bv[sizeof(buf) / PAGE_SIZE]; - } o; - struct closure cl; + struct bch_write_op op; + struct bio_vec bv[WRITE_DATA_BUF / PAGE_SIZE]; BUG_ON(dst_offset & (block_bytes(c) - 1)); BUG_ON(len & (block_bytes(c) - 1)); + BUG_ON(len > WRITE_DATA_BUF); - closure_init_stack(&cl); - - bio_init(&o.op.wbio.bio, o.bv, ARRAY_SIZE(o.bv)); - o.op.wbio.bio.bi_iter.bi_size = len; - bch2_bio_map(&o.op.wbio.bio, buf); + bio_init(&op.wbio.bio, NULL, bv, ARRAY_SIZE(bv), 0); + bch2_bio_map(&op.wbio.bio, buf, len); - bch2_write_op_init(&o.op, c, bch2_opts_to_inode_opts(c->opts)); - o.op.write_point = writepoint_hashed(0); - o.op.nr_replicas = 1; - o.op.pos = POS(dst_inode->bi_inum, dst_offset >> 9); + bch2_write_op_init(&op, c, bch2_opts_to_inode_opts(c->opts)); + op.write_point = writepoint_hashed(0); + op.nr_replicas = 1; + op.subvol = 1; + op.pos = SPOS(dst_inode->bi_inum, dst_offset >> 9, U32_MAX); + op.flags |= BCH_WRITE_SYNC; - int ret = bch2_disk_reservation_get(c, &o.op.res, len >> 9, + int ret = bch2_disk_reservation_get(c, &op.res, len >> 9, c->opts.data_replicas, 0); if (ret) - die("error reserving space in new filesystem: %s", strerror(-ret)); + die("error reserving space in new filesystem: %s", bch2_err_str(ret)); - closure_call(&o.op.cl, bch2_write, NULL, &cl); - closure_sync(&cl); + closure_call(&op.cl, bch2_write, NULL, NULL); + BUG_ON(!(op.flags & BCH_WRITE_DONE)); dst_inode->bi_sectors += len >> 9; + + if (op.error) + die("write error: %s", bch2_err_str(op.error)); } static void copy_data(struct bch_fs *c, @@ -317,7 +313,7 @@ static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst, while (length) { struct bkey_i_extent *e; - BKEY_PADDED(k) k; + BKEY_PADDED_ONSTACK(k, BKEY_EXTENT_VAL_U64s_MAX) k; u64 b = sector_to_bucket(ca, physical); struct disk_reservation res; unsigned sectors; @@ -330,27 +326,23 @@ static void link_data(struct bch_fs *c, struct bch_inode_unpacked *dst, e = bkey_extent_init(&k.k); e->k.p.inode = dst->bi_inum; e->k.p.offset = logical + sectors; + e->k.p.snapshot = U32_MAX; e->k.size = sectors; bch2_bkey_append_ptr(&e->k_i, (struct bch_extent_ptr) { .offset = physical, .dev = 0, - .gen = bucket(ca, b)->mark.gen, + .gen = *bucket_gen(ca, b), }); - bucket_set_dirty(ca, b); - ret = bch2_disk_reservation_get(c, &res, sectors, 1, BCH_DISK_RESERVATION_NOFAIL); if (ret) die("error reserving space in new filesystem: %s", - strerror(-ret)); - - bch2_mark_bkey_replicas(c, extent_i_to_s_c(e).s_c); + bch2_err_str(ret)); - ret = bch2_btree_insert(c, BTREE_ID_EXTENTS, &e->k_i, - &res, NULL, 0); + ret = bch2_btree_insert(c, BTREE_ID_extents, &e->k_i, &res, 0); if (ret) - die("btree insert error %s", strerror(-ret)); + die("btree insert error %s", bch2_err_str(ret)); bch2_disk_reservation_put(c, &res); @@ -383,8 +375,13 @@ static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst, fsync(src_fd); break; } + fiemap_iter_exit(&iter); fiemap_for_each(src_fd, iter, e) { + u64 src_max = roundup(src_size, block_bytes(c)); + + e.fe_length = min(e.fe_length, src_max - e.fe_logical); + if ((e.fe_logical & (block_bytes(c) - 1)) || (e.fe_length & (block_bytes(c) - 1))) die("Unaligned extent in %s - can't handle", src_path); @@ -416,6 +413,7 @@ static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst, range_add(extents, e.fe_physical, e.fe_length); link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length); } + fiemap_iter_exit(&iter); } struct copy_fs_state { @@ -446,6 +444,7 @@ static void copy_dir(struct copy_fs_state *s, if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..") || + !strcmp(d->d_name, "lost+found") || stat.st_ino == s->bcachefs_inum) continue; @@ -512,6 +511,7 @@ next: if (errno) die("readdir error: %m"); + closedir(dir); } static ranges reserve_new_fs_space(const char *file_path, unsigned block_size, @@ -539,7 +539,7 @@ static ranges reserve_new_fs_space(const char *file_path, unsigned block_size, struct fiemap_iter iter; struct fiemap_extent e; - ranges extents = { NULL }; + ranges extents = { 0 }; fiemap_for_each(fd, iter, e) { if (e.fe_flags & (FIEMAP_EXTENT_UNKNOWN| @@ -554,6 +554,7 @@ static ranges reserve_new_fs_space(const char *file_path, unsigned block_size, range_add(&extents, e.fe_physical, e.fe_length); } + fiemap_iter_exit(&iter); close(fd); ranges_sort_merge(&extents); @@ -587,9 +588,10 @@ static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path, syncfs(src_fd); struct bch_inode_unpacked root_inode; - int ret = bch2_inode_find_by_inum(c, BCACHEFS_ROOT_INO, &root_inode); + int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO }, + &root_inode); if (ret) - die("error looking up root directory: %s", strerror(-ret)); + die("error looking up root directory: %s", bch2_err_str(ret)); if (fchdir(src_fd)) die("chdir error: %m"); @@ -611,26 +613,24 @@ static void copy_fs(struct bch_fs *c, int src_fd, const char *src_path, update_inode(c, &root_inode); - darray_free(s.extents); + darray_exit(&s.extents); genradix_free(&s.hardlinks); - - bool wrote; - bch2_alloc_write(c, false, &wrote); } -static void find_superblock_space(ranges extents, struct dev_opts *dev) +static void find_superblock_space(ranges extents, + struct format_opts opts, + struct dev_opts *dev) { - struct range *i; - - darray_foreach(i, extents) { + darray_for_each(extents, i) { u64 start = round_up(max(256ULL << 10, i->start), dev->bucket_size << 9); u64 end = round_down(i->end, dev->bucket_size << 9); - if (start + (128 << 10) <= end) { + /* Need space for two superblocks: */ + if (start + (opts.superblock_size << 9) * 2 <= end) { dev->sb_offset = start >> 9; - dev->sb_end = dev->sb_offset + 256; + dev->sb_end = dev->sb_offset + opts.superblock_size * 2; return; } } @@ -649,7 +649,7 @@ static void migrate_usage(void) " --no_passphrase Don't encrypt master encryption key\n" " -F Force, even if metadata file already exists\n" " -h Display this help and exit\n" - "Report bugs to "); + "Report bugs to "); } static const struct option migrate_opts[] = { @@ -676,30 +676,34 @@ static int migrate_fs(const char *fs_path, struct dev_opts dev = dev_opts_default(); dev.path = dev_t_to_path(stat.st_dev); - dev.fd = xopen(dev.path, O_RDWR); + dev.bdev = blkdev_get_by_path(dev.path, BLK_OPEN_READ|BLK_OPEN_WRITE, &dev, NULL); - opt_set(fs_opts, block_size, get_blocksize(dev.path, dev.fd)); + opt_set(fs_opts, block_size, get_blocksize(dev.bdev->bd_buffered_fd)); char *file_path = mprintf("%s/bcachefs", fs_path); printf("Creating new filesystem on %s in space reserved at %s\n", dev.path, file_path); - bch2_pick_bucket_size(fs_opts, &dev); + dev.size = get_size(dev.bdev->bd_buffered_fd); + dev.bucket_size = bch2_pick_bucket_size(fs_opts, &dev); + dev.nbuckets = dev.size / dev.bucket_size; + + bch2_check_bucket_size(fs_opts, &dev); u64 bcachefs_inum; ranges extents = reserve_new_fs_space(file_path, - fs_opts.block_size << 9, - get_size(dev.path, dev.fd) / 5, + fs_opts.block_size >> 9, + get_size(dev.bdev->bd_buffered_fd) / 5, &bcachefs_inum, stat.st_dev, force); - find_superblock_space(extents, &dev); + find_superblock_space(extents, format_opts, &dev); struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts,format_opts, &dev, 1); u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]); if (format_opts.passphrase) - bch2_add_key(sb, format_opts.passphrase); + bch2_add_key(sb, "user", "user", format_opts.passphrase); free(sb); @@ -710,16 +714,17 @@ static int migrate_fs(const char *fs_path, opt_set(opts, sb, sb_offset); opt_set(opts, nostart, true); opt_set(opts, noexcl, true); + opt_set(opts, buckets_nouse, true); c = bch2_fs_open(path, 1, opts); if (IS_ERR(c)) - die("Error opening new filesystem: %s", strerror(-PTR_ERR(c))); + die("Error opening new filesystem: %s", bch2_err_str(PTR_ERR(c))); mark_unreserved_space(c, extents); - const char *err = bch2_fs_start(c); - if (err) - die("Error starting new filesystem: %s", err); + int ret = bch2_fs_start(c); + if (ret) + die("Error starting new filesystem: %s", bch2_err_str(ret)); copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents); @@ -731,7 +736,7 @@ static int migrate_fs(const char *fs_path, c = bch2_fs_open(path, 1, opts); if (IS_ERR(c)) - die("Error opening new filesystem: %s", strerror(-PTR_ERR(c))); + die("Error opening new filesystem: %s", bch2_err_str(PTR_ERR(c))); bch2_fs_stop(c); printf("fsck complete\n"); @@ -784,15 +789,17 @@ int cmd_migrate(int argc, char *argv[]) } if (!fs_path) - die("Please specify a filesytem to migrate"); + die("Please specify a filesystem to migrate"); if (format_opts.encrypted && !no_passphrase) format_opts.passphrase = read_passphrase_twice("Enter passphrase: "); - return migrate_fs(fs_path, - fs_opt_strs, - fs_opts, - format_opts, force); + int ret = migrate_fs(fs_path, + fs_opt_strs, + fs_opts, + format_opts, force); + bch2_opt_strs_free(&fs_opt_strs); + return ret; } static void migrate_superblock_usage(void) @@ -804,7 +811,7 @@ static void migrate_superblock_usage(void) " -d device Device to create superblock for\n" " -o offset Offset of existing superblock\n" " -h Display this help and exit\n" - "Report bugs to "); + "Report bugs to "); } int cmd_migrate_superblock(int argc, char *argv[])