#include "libbcachefs/btree_update.h"
#include "libbcachefs/buckets.h"
#include "libbcachefs/dirent.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"
struct bkey_inode_buf packed;
int ret;
- bch2_inode_pack(c, &packed, inode);
- ret = bch2_btree_insert(c, BTREE_ID_INODES, &packed.inode.k_i,
- NULL, NULL, 0);
+ bch2_inode_pack(&packed, inode);
+ 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 updating inode: %s", strerror(-ret));
+ die("error updating inode: %s", bch2_err_str(ret));
}
static void create_link(struct bch_fs *c,
struct bch_inode_unpacked inode;
int ret = bch2_trans_do(c, NULL, NULL, 0,
- bch2_link_trans(&trans, parent->bi_inum, inum,
- &parent_u, &inode, &qstr));
+ 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", strerror(-ret));
+ die("error creating hardlink: %s", bch2_err_str(ret));
}
static struct bch_inode_unpacked create_file(struct bch_fs *c,
struct qstr qstr = QSTR(name);
struct bch_inode_unpacked new_inode;
+ bch2_inode_init_early(c, &new_inode);
+
int ret = bch2_trans_do(c, NULL, NULL, 0,
- bch2_create_trans(&trans,
- parent->bi_inum, parent,
+ bch2_create_trans(trans,
+ (subvol_inum) { 1, parent->bi_inum }, parent,
&new_inode, &qstr,
- uid, gid, mode, rdev, NULL, NULL));
+ uid, gid, mode, rdev, NULL, NULL,
+ (subvol_inum) {}, 0));
if (ret)
- die("error creating file: %s", strerror(-ret));
+ die("error creating %s: %s", name, bch2_err_str(ret));
return new_inode;
}
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, NULL, 0,
- bch2_xattr_set(&trans, dst->bi_inum, &hash_info, attr,
+ 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));
- bch2_bio_map(&o.op.wbio.bio, buf, len);
+ 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,
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;
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),
});
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);
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);
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 {
if (!strcmp(d->d_name, ".") ||
!strcmp(d->d_name, "..") ||
+ !strcmp(d->d_name, "lost+found") ||
stat.st_ino == s->bcachefs_inum)
continue;
if (errno)
die("readdir error: %m");
+ closedir(dir);
}
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|
range_add(&extents, e.fe_physical, e.fe_length);
}
+ fiemap_iter_exit(&iter);
close(fd);
ranges_sort_merge(&extents);
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");
update_inode(c, &root_inode);
- darray_free(s.extents);
+ darray_exit(&s.extents);
genradix_free(&s.hardlinks);
-
- bch2_alloc_write(c, false);
}
-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;
}
}
" --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 <linux-bcache@vger.kernel.org>");
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
}
static const struct option migrate_opts[] = {
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_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_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_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);
+ 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);
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);
int ret = bch2_fs_start(c);
if (ret)
- die("Error starting new filesystem: %s", strerror(-ret));
+ die("Error starting new filesystem: %s", bch2_err_str(ret));
copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents);
printf("Migrate complete, running fsck:\n");
opt_set(opts, nostart, false);
opt_set(opts, nochanges, true);
+ opt_set(opts, read_only, 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)));
bch2_fs_stop(c);
printf("fsck complete\n");
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)
" -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 <linux-bcache@vger.kernel.org>");
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
}
int cmd_migrate_superblock(int argc, char *argv[])