mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-04-01 00:00:03 +03:00
Migrate tool fixes
Migrate now works: there is an inconsequential free space inconsistency after marking the new superblock (in migrate_superblock), which we're hacking around with a fsck. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
5504533986
commit
6657ce2de3
@ -121,7 +121,7 @@ void build_fs(struct bch_fs *c, const char *src_path)
|
||||
if (!S_ISDIR(stat.st_mode))
|
||||
die("%s is not a directory", src_path);
|
||||
|
||||
copy_fs(c, src_fd, src_path, &s);
|
||||
copy_fs(c, src_fd, src_path, &s, 0);
|
||||
}
|
||||
|
||||
int cmd_format(int argc, char *argv[])
|
||||
|
@ -252,16 +252,14 @@ static int migrate_fs(const char *fs_path,
|
||||
|
||||
free(sb);
|
||||
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
struct bch_fs *c = NULL;
|
||||
char *path[1] = { dev->path };
|
||||
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
opt_set(opts, sb, sb_offset);
|
||||
opt_set(opts, nostart, true);
|
||||
opt_set(opts, noexcl, true);
|
||||
opt_set(opts, nostart, true);
|
||||
|
||||
c = bch2_fs_open(path, 1, opts);
|
||||
struct bch_fs *c = bch2_fs_open(path, 1, opts);
|
||||
if (IS_ERR(c))
|
||||
die("Error opening new filesystem: %s", bch2_err_str(PTR_ERR(c)));
|
||||
|
||||
@ -269,10 +267,6 @@ static int migrate_fs(const char *fs_path,
|
||||
if (ret)
|
||||
die("Error allocating buckets_nouse: %s", bch2_err_str(ret));
|
||||
|
||||
ret = bch2_fs_start(c);
|
||||
if (IS_ERR(c))
|
||||
die("Error starting new filesystem: %s", bch2_err_str(ret));
|
||||
|
||||
mark_unreserved_space(c, extents);
|
||||
|
||||
ret = bch2_fs_start(c);
|
||||
@ -286,7 +280,10 @@ static int migrate_fs(const char *fs_path,
|
||||
.type = BCH_MIGRATE_migrate,
|
||||
};
|
||||
|
||||
copy_fs(c, fs_fd, fs_path, &s);
|
||||
u64 reserve_start = round_up((format_opts.superblock_size * 2 + 8) << 9,
|
||||
dev->opts.bucket_size);
|
||||
|
||||
copy_fs(c, fs_fd, fs_path, &s, reserve_start);
|
||||
|
||||
bch2_fs_stop(c);
|
||||
|
||||
@ -378,7 +375,7 @@ static void migrate_superblock_usage(void)
|
||||
int cmd_migrate_superblock(int argc, char *argv[])
|
||||
{
|
||||
char *dev = NULL;
|
||||
u64 offset = 0;
|
||||
u64 sb_offset = 0;
|
||||
int opt, ret;
|
||||
|
||||
while ((opt = getopt(argc, argv, "d:o:h")) != -1)
|
||||
@ -387,7 +384,7 @@ int cmd_migrate_superblock(int argc, char *argv[])
|
||||
dev = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
ret = kstrtou64(optarg, 10, &offset);
|
||||
ret = kstrtou64(optarg, 10, &sb_offset);
|
||||
if (ret)
|
||||
die("Invalid offset");
|
||||
break;
|
||||
@ -399,29 +396,67 @@ int cmd_migrate_superblock(int argc, char *argv[])
|
||||
if (!dev)
|
||||
die("Please specify a device");
|
||||
|
||||
if (!offset)
|
||||
if (!sb_offset)
|
||||
die("Please specify offset of existing superblock");
|
||||
|
||||
int fd = xopen(dev, O_RDWR);
|
||||
struct bch_sb *sb = __bch2_super_read(fd, offset);
|
||||
struct bch_sb *sb = __bch2_super_read(fd, sb_offset);
|
||||
unsigned sb_size = 1U << sb->layout.sb_max_size_bits;
|
||||
|
||||
if (sb->layout.nr_superblocks >= ARRAY_SIZE(sb->layout.sb_offset))
|
||||
die("Can't add superblock: no space left in superblock layout");
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < sb->layout.nr_superblocks; i++)
|
||||
if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR)
|
||||
die("Superblock layout already has default superblock");
|
||||
for (unsigned i = 0; i < sb->layout.nr_superblocks; i++)
|
||||
if (le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR ||
|
||||
le64_to_cpu(sb->layout.sb_offset[i]) == BCH_SB_SECTOR + sb_size)
|
||||
die("Superblock layout already has default superblocks");
|
||||
|
||||
memmove(&sb->layout.sb_offset[1],
|
||||
memmove(&sb->layout.sb_offset[2],
|
||||
&sb->layout.sb_offset[0],
|
||||
sb->layout.nr_superblocks * sizeof(u64));
|
||||
sb->layout.nr_superblocks++;
|
||||
|
||||
sb->layout.nr_superblocks += 2;
|
||||
sb->layout.sb_offset[0] = cpu_to_le64(BCH_SB_SECTOR);
|
||||
sb->layout.sb_offset[1] = cpu_to_le64(BCH_SB_SECTOR + sb_size);
|
||||
|
||||
bch2_super_write(fd, sb);
|
||||
close(fd);
|
||||
|
||||
/* mark new superblocks */
|
||||
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
opt_set(opts, nostart, true);
|
||||
opt_set(opts, sb, sb_offset);
|
||||
|
||||
struct bch_fs *c = bch2_fs_open(&dev, 1, opts);
|
||||
ret = PTR_ERR_OR_ZERO(c) ?:
|
||||
bch2_buckets_nouse_alloc(c);
|
||||
if (ret)
|
||||
die("error opening filesystem: %s", bch2_err_str(ret));
|
||||
|
||||
struct bch_dev *ca = c->devs[0];
|
||||
for (u64 b = 0; bucket_to_sector(ca, b) < BCH_SB_SECTOR + sb_size * 2; b++)
|
||||
set_bit(b, ca->buckets_nouse);
|
||||
|
||||
ret = bch2_fs_start(c);
|
||||
if (ret)
|
||||
die("Error starting filesystem: %s", bch2_err_str(ret));
|
||||
|
||||
bch2_fs_stop(c);
|
||||
|
||||
opts = bch2_opts_empty();
|
||||
opt_set(opts, fsck, true);
|
||||
opt_set(opts, fix_errors, true);
|
||||
|
||||
/*
|
||||
* Hack: the free space counters are coming out wrong after marking the
|
||||
* new superblock, but it's just the device counters so it's
|
||||
* inconsequential:
|
||||
*/
|
||||
|
||||
c = bch2_fs_open(&dev, 1, opts);
|
||||
ret = PTR_ERR_OR_ZERO(c);
|
||||
if (ret)
|
||||
die("error opening filesystem: %s", bch2_err_str(ret));
|
||||
bch2_fs_stop(c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -264,7 +264,8 @@ void copy_link(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
||||
|
||||
static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
||||
int src_fd, u64 src_size,
|
||||
char *src_path, struct copy_fs_state *s)
|
||||
char *src_path, struct copy_fs_state *s,
|
||||
u64 reserve_start)
|
||||
{
|
||||
struct fiemap_iter iter;
|
||||
struct fiemap_extent e;
|
||||
@ -295,11 +296,8 @@ static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the data is below 1 MB, copy it so it doesn't conflict
|
||||
* with bcachefs's potentially larger superblock:
|
||||
*/
|
||||
if (e.fe_physical < 1 << 20) {
|
||||
/* If the data is in bcachefs's superblock region, copy it: */
|
||||
if (e.fe_physical < reserve_start) {
|
||||
copy_data(c, dst, src_fd, e.fe_logical,
|
||||
e.fe_logical + min(src_size - e.fe_logical,
|
||||
e.fe_length));
|
||||
@ -318,7 +316,8 @@ static void copy_file(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
||||
static void copy_dir(struct copy_fs_state *s,
|
||||
struct bch_fs *c,
|
||||
struct bch_inode_unpacked *dst,
|
||||
int src_fd, const char *src_path)
|
||||
int src_fd, const char *src_path,
|
||||
u64 reserve_start)
|
||||
{
|
||||
DIR *dir = fdopendir(src_fd);
|
||||
struct dirent *d;
|
||||
@ -369,7 +368,7 @@ static void copy_dir(struct copy_fs_state *s,
|
||||
switch (mode_to_type(stat.st_mode)) {
|
||||
case DT_DIR:
|
||||
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
||||
copy_dir(s, c, &inode, fd, child_path);
|
||||
copy_dir(s, c, &inode, fd, child_path, reserve_start);
|
||||
close(fd);
|
||||
break;
|
||||
case DT_REG:
|
||||
@ -377,7 +376,7 @@ static void copy_dir(struct copy_fs_state *s,
|
||||
|
||||
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
||||
copy_file(c, &inode, fd, stat.st_size,
|
||||
child_path, s);
|
||||
child_path, s, reserve_start);
|
||||
close(fd);
|
||||
break;
|
||||
case DT_LNK:
|
||||
@ -409,7 +408,8 @@ next:
|
||||
|
||||
static void reserve_old_fs_space(struct bch_fs *c,
|
||||
struct bch_inode_unpacked *root_inode,
|
||||
ranges *extents)
|
||||
ranges *extents,
|
||||
u64 reserve_start)
|
||||
{
|
||||
struct bch_dev *ca = c->devs[0];
|
||||
struct bch_inode_unpacked dst;
|
||||
@ -422,14 +422,20 @@ static void reserve_old_fs_space(struct bch_fs *c,
|
||||
|
||||
ranges_sort_merge(extents);
|
||||
|
||||
for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i)
|
||||
link_data(c, &dst, i.start, i.start, i.end - i.start);
|
||||
for_each_hole(iter, *extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i) {
|
||||
if (i.end <= reserve_start)
|
||||
continue;
|
||||
|
||||
u64 start = max(i.start, reserve_start);
|
||||
|
||||
link_data(c, &dst, start, start, i.end - start);
|
||||
}
|
||||
|
||||
update_inode(c, &dst);
|
||||
}
|
||||
|
||||
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
||||
struct copy_fs_state *s)
|
||||
struct copy_fs_state *s, u64 reserve_start)
|
||||
{
|
||||
syncfs(src_fd);
|
||||
|
||||
@ -448,10 +454,10 @@ void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
||||
|
||||
|
||||
/* now, copy: */
|
||||
copy_dir(s, c, &root_inode, src_fd, src_path);
|
||||
copy_dir(s, c, &root_inode, src_fd, src_path, reserve_start);
|
||||
|
||||
if (BCH_MIGRATE_migrate == s->type)
|
||||
reserve_old_fs_space(c, &root_inode, &s->extents);
|
||||
reserve_old_fs_space(c, &root_inode, &s->extents, reserve_start);
|
||||
|
||||
update_inode(c, &root_inode);
|
||||
|
||||
|
@ -50,5 +50,5 @@ struct copy_fs_state {
|
||||
* initialized (`hardlinks` is initialized with zeroes).
|
||||
*/
|
||||
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
||||
struct copy_fs_state *s);
|
||||
struct copy_fs_state *s, u64);
|
||||
#endif /* _LIBBCACHE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user