mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-09 00:00:17 +03:00
posix_to_bcachefs: cleanup
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
c074341f16
commit
b02c3e9682
@ -102,12 +102,12 @@ static const struct option format_opts[] = {
|
|||||||
};
|
};
|
||||||
#undef x
|
#undef x
|
||||||
|
|
||||||
static void build_fs(struct bch_fs *c, const char *src_path)
|
static int build_fs(struct bch_fs *c, const char *src_path)
|
||||||
{
|
{
|
||||||
struct copy_fs_state s = {};
|
struct copy_fs_state s = {};
|
||||||
int src_fd = xopen(src_path, O_RDONLY|O_NOATIME);
|
int src_fd = xopen(src_path, O_RDONLY|O_NOATIME);
|
||||||
|
|
||||||
copy_fs(c, src_fd, src_path, &s, 0);
|
return copy_fs(c, &s, src_fd, src_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_format(int argc, char *argv[])
|
int cmd_format(int argc, char *argv[])
|
||||||
|
|||||||
@ -273,7 +273,9 @@ static void image_create(struct bch_opt_strs fs_opt_strs,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
struct copy_fs_state s = {};
|
struct copy_fs_state s = {};
|
||||||
copy_fs(c, src_fd, src_path, &s, 0);
|
ret = copy_fs(c, &s, src_fd, src_path);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (verbosity > 1)
|
if (verbosity > 1)
|
||||||
printf("moving non-alloc btree to primary device\n");
|
printf("moving non-alloc btree to primary device\n");
|
||||||
|
|||||||
@ -279,17 +279,19 @@ static int migrate_fs(const char *fs_path,
|
|||||||
.dev = stat.st_dev,
|
.dev = stat.st_dev,
|
||||||
.extents = extents,
|
.extents = extents,
|
||||||
.type = BCH_MIGRATE_migrate,
|
.type = BCH_MIGRATE_migrate,
|
||||||
|
.reserve_start = roundup((format_opts.superblock_size * 2 + 8) << 9,
|
||||||
|
bucket_bytes(c->devs[0])),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BUG_ON(!s.reserve_start);
|
||||||
|
|
||||||
u64 reserve_start = roundup((format_opts.superblock_size * 2 + 8) << 9,
|
ret = copy_fs(c, &s, fs_fd, fs_path);
|
||||||
bucket_bytes(c->devs[0]));
|
|
||||||
BUG_ON(!reserve_start);
|
|
||||||
|
|
||||||
copy_fs(c, fs_fd, fs_path, &s, reserve_start);
|
|
||||||
|
|
||||||
bch2_fs_stop(c);
|
bch2_fs_stop(c);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
printf("Migrate complete, running fsck:\n");
|
printf("Migrate complete, running fsck:\n");
|
||||||
opt_set(opts, nostart, false);
|
opt_set(opts, nostart, false);
|
||||||
opt_set(opts, nochanges, true);
|
opt_set(opts, nochanges, true);
|
||||||
|
|||||||
@ -338,10 +338,10 @@ void copy_link(struct bch_fs *c,
|
|||||||
write_data(c, dst, 0, src_buf, round_up(ret, block_bytes(c)));
|
write_data(c, dst, 0, src_buf, round_up(ret, block_bytes(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void link_file_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
static void link_file_data(struct bch_fs *c,
|
||||||
int src_fd, u64 src_size,
|
struct copy_fs_state *s,
|
||||||
char *src_path, struct copy_fs_state *s,
|
struct bch_inode_unpacked *dst,
|
||||||
u64 reserve_start)
|
int src_fd, char *src_path, u64 src_size)
|
||||||
{
|
{
|
||||||
struct fiemap_iter iter;
|
struct fiemap_iter iter;
|
||||||
struct fiemap_extent e;
|
struct fiemap_extent e;
|
||||||
@ -354,10 +354,14 @@ static void link_file_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
|||||||
fiemap_iter_exit(&iter);
|
fiemap_iter_exit(&iter);
|
||||||
|
|
||||||
fiemap_for_each(src_fd, iter, e) {
|
fiemap_for_each(src_fd, iter, e) {
|
||||||
|
s->total_input += e.fe_length;
|
||||||
|
|
||||||
u64 src_max = roundup(src_size, block_bytes(c));
|
u64 src_max = roundup(src_size, block_bytes(c));
|
||||||
|
|
||||||
e.fe_length = min(e.fe_length, src_max - e.fe_logical);
|
e.fe_length = min(e.fe_length, src_max - e.fe_logical);
|
||||||
|
|
||||||
|
unsigned visible_len = min(src_size - e.fe_logical, e.fe_length);
|
||||||
|
|
||||||
if ((e.fe_logical & (block_bytes(c) - 1)) ||
|
if ((e.fe_logical & (block_bytes(c) - 1)) ||
|
||||||
(e.fe_length & (block_bytes(c) - 1)))
|
(e.fe_length & (block_bytes(c) - 1)))
|
||||||
die("Unaligned extent in %s - can't handle", src_path);
|
die("Unaligned extent in %s - can't handle", src_path);
|
||||||
@ -367,16 +371,16 @@ static void link_file_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
|||||||
FIEMAP_EXTENT_NOT_ALIGNED|
|
FIEMAP_EXTENT_NOT_ALIGNED|
|
||||||
FIEMAP_EXTENT_DATA_INLINE))) {
|
FIEMAP_EXTENT_DATA_INLINE))) {
|
||||||
copy_data(c, dst, src_fd, e.fe_logical,
|
copy_data(c, dst, src_fd, e.fe_logical,
|
||||||
e.fe_logical + min(src_size - e.fe_logical,
|
e.fe_logical + visible_len);
|
||||||
e.fe_length));
|
s->total_wrote += visible_len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the data is in bcachefs's superblock region, copy it: */
|
/* If the data is in bcachefs's superblock region, copy it: */
|
||||||
if (e.fe_physical < reserve_start) {
|
if (e.fe_physical < s->reserve_start) {
|
||||||
copy_data(c, dst, src_fd, e.fe_logical,
|
copy_data(c, dst, src_fd, e.fe_logical,
|
||||||
e.fe_logical + min(src_size - e.fe_logical,
|
e.fe_logical + visible_len);
|
||||||
e.fe_length));
|
s->total_wrote += visible_len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +389,7 @@ static void link_file_data(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
|||||||
|
|
||||||
range_add(&s->extents, e.fe_physical, e.fe_length);
|
range_add(&s->extents, e.fe_physical, e.fe_length);
|
||||||
link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
|
link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length);
|
||||||
|
s->total_linked += e.fe_length;
|
||||||
}
|
}
|
||||||
fiemap_iter_exit(&iter);
|
fiemap_iter_exit(&iter);
|
||||||
}
|
}
|
||||||
@ -474,10 +479,10 @@ static struct range seek_mismatch_aligned(const char *buf1, const char *buf2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void copy_sync_file_range(struct bch_fs *c,
|
static void copy_sync_file_range(struct bch_fs *c,
|
||||||
|
struct copy_fs_state *s,
|
||||||
subvol_inum dst_inum,
|
subvol_inum dst_inum,
|
||||||
struct bch_inode_unpacked *dst,
|
struct bch_inode_unpacked *dst,
|
||||||
int src_fd, u64 src_size,
|
int src_fd, u64 src_size,
|
||||||
u64 *total_wrote,
|
|
||||||
struct range r)
|
struct range r)
|
||||||
{
|
{
|
||||||
while (r.start != r.end) {
|
while (r.start != r.end) {
|
||||||
@ -495,7 +500,7 @@ static void copy_sync_file_range(struct bch_fs *c,
|
|||||||
m.end, b, c->opts.block_size)).end) {
|
m.end, b, c->opts.block_size)).end) {
|
||||||
write_data(c, dst, r.start + m.start,
|
write_data(c, dst, r.start + m.start,
|
||||||
src_buf + m.start, m.end - m.start);
|
src_buf + m.start, m.end - m.start);
|
||||||
*total_wrote += m.end - m.start;
|
s->total_wrote += m.end - m.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
r.start += b;
|
r.start += b;
|
||||||
@ -503,10 +508,10 @@ static void copy_sync_file_range(struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void copy_sync_file_data(struct bch_fs *c,
|
static void copy_sync_file_data(struct bch_fs *c,
|
||||||
|
struct copy_fs_state *s,
|
||||||
subvol_inum dst_inum,
|
subvol_inum dst_inum,
|
||||||
struct bch_inode_unpacked *dst,
|
struct bch_inode_unpacked *dst,
|
||||||
int src_fd, u64 src_size,
|
int src_fd, u64 src_size)
|
||||||
u64 *total_wrote)
|
|
||||||
{
|
{
|
||||||
s64 i_sectors_delta = 0;
|
s64 i_sectors_delta = 0;
|
||||||
|
|
||||||
@ -521,7 +526,9 @@ static void copy_sync_file_data(struct bch_fs *c,
|
|||||||
die("bch2_fpunch error: %s", bch2_err_str(ret));
|
die("bch2_fpunch error: %s", bch2_err_str(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_sync_file_range(c, dst_inum, dst, src_fd, src_size, total_wrote, next);
|
copy_sync_file_range(c, s, dst_inum, dst, src_fd, src_size, next);
|
||||||
|
|
||||||
|
s->total_input += next.end - next.start;
|
||||||
|
|
||||||
prev = next;
|
prev = next;
|
||||||
}
|
}
|
||||||
@ -594,6 +601,7 @@ static int recursive_remove(struct bch_fs *c,
|
|||||||
|
|
||||||
struct bch_inode_unpacked child;
|
struct bch_inode_unpacked child;
|
||||||
int ret = bch2_inode_find_by_inum(c, child_inum, &child);
|
int ret = bch2_inode_find_by_inum(c, child_inum, &child);
|
||||||
|
bch_err_msg(c, ret, "looking up inode for %s", d->d_name);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -619,12 +627,16 @@ static int recursive_remove(struct bch_fs *c,
|
|||||||
ret = bch2_trans_commit_do(c, NULL, NULL,
|
ret = bch2_trans_commit_do(c, NULL, NULL,
|
||||||
BCH_TRANS_COMMIT_no_enospc,
|
BCH_TRANS_COMMIT_no_enospc,
|
||||||
bch2_unlink_trans(trans, dir_inum, dir, &child, &d_name, false));
|
bch2_unlink_trans(trans, dir_inum, dir, &child, &d_name, false));
|
||||||
|
bch_err_msg(c, ret, "unlinking %s", d->d_name);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return !child.bi_nlink
|
if (!(child.bi_flags & BCH_INODE_unlinked))
|
||||||
? bch2_inode_rm(c, child_inum)
|
return 0;
|
||||||
: 0;
|
|
||||||
|
ret = bch2_inode_rm(c, child_inum);
|
||||||
|
bch_err_msg(c, ret, "deleting %s", d->d_name);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int delete_non_matching_dirents(struct bch_fs *c,
|
static int delete_non_matching_dirents(struct bch_fs *c,
|
||||||
@ -642,7 +654,7 @@ static int delete_non_matching_dirents(struct bch_fs *c,
|
|||||||
struct dirent *src_d = src_dirents.data;
|
struct dirent *src_d = src_dirents.data;
|
||||||
darray_for_each(dst_dirents, dst_d) {
|
darray_for_each(dst_dirents, dst_d) {
|
||||||
while (src_d < &darray_top(src_dirents) &&
|
while (src_d < &darray_top(src_dirents) &&
|
||||||
dirent_cmp(src_d,dst_d) < 0)
|
dirent_cmp(src_d, dst_d) < 0)
|
||||||
src_d++;
|
src_d++;
|
||||||
|
|
||||||
if (src_d == &darray_top(src_dirents) ||
|
if (src_d == &darray_top(src_dirents) ||
|
||||||
@ -660,16 +672,13 @@ static int delete_non_matching_dirents(struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
darray_exit(&dst_dirents);
|
darray_exit(&dst_dirents);
|
||||||
bch_err_fn(c, ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_dir(struct copy_fs_state *s,
|
static int copy_dir(struct bch_fs *c,
|
||||||
struct bch_fs *c,
|
struct copy_fs_state *s,
|
||||||
struct bch_inode_unpacked *dst,
|
struct bch_inode_unpacked *dst,
|
||||||
int src_fd, const char *src_path,
|
int src_fd, const char *src_path)
|
||||||
u64 reserve_start,
|
|
||||||
u64 *total_wrote)
|
|
||||||
{
|
{
|
||||||
lseek(src_fd, 0, SEEK_SET);
|
lseek(src_fd, 0, SEEK_SET);
|
||||||
|
|
||||||
@ -708,6 +717,8 @@ static void copy_dir(struct copy_fs_state *s,
|
|||||||
if (BCH_MIGRATE_migrate == s->type && stat.st_ino == s->bcachefs_inum)
|
if (BCH_MIGRATE_migrate == s->type && stat.st_ino == s->bcachefs_inum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
s->total_files++;
|
||||||
|
|
||||||
char *child_path = mprintf("%s/%s", src_path, d->d_name);
|
char *child_path = mprintf("%s/%s", src_path, d->d_name);
|
||||||
|
|
||||||
if (s->type == BCH_MIGRATE_migrate && stat.st_dev != s->dev)
|
if (s->type == BCH_MIGRATE_migrate && stat.st_dev != s->dev)
|
||||||
@ -737,19 +748,20 @@ static void copy_dir(struct copy_fs_state *s,
|
|||||||
switch (mode_to_type(stat.st_mode)) {
|
switch (mode_to_type(stat.st_mode)) {
|
||||||
case DT_DIR:
|
case DT_DIR:
|
||||||
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
||||||
copy_dir(s, c, &inode, fd, child_path,
|
ret = copy_dir(c, s, &inode, fd, child_path);
|
||||||
reserve_start, total_wrote);
|
if (ret)
|
||||||
|
goto err;
|
||||||
break;
|
break;
|
||||||
case DT_REG:
|
case DT_REG:
|
||||||
inode.bi_size = stat.st_size;
|
inode.bi_size = stat.st_size;
|
||||||
|
|
||||||
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
fd = xopen(d->d_name, O_RDONLY|O_NOATIME);
|
||||||
if (s->type == BCH_MIGRATE_migrate)
|
if (s->type == BCH_MIGRATE_migrate)
|
||||||
link_file_data(c, &inode, fd, stat.st_size,
|
link_file_data(c, s, &inode,
|
||||||
child_path, s, reserve_start);
|
fd, child_path, stat.st_size);
|
||||||
else
|
else
|
||||||
copy_sync_file_data(c, dst_child_inum, &inode,
|
copy_sync_file_data(c, s, dst_child_inum, &inode,
|
||||||
fd, stat.st_size, total_wrote);
|
fd, stat.st_size);
|
||||||
xclose(fd);
|
xclose(fd);
|
||||||
break;
|
break;
|
||||||
case DT_LNK:
|
case DT_LNK:
|
||||||
@ -776,6 +788,7 @@ next:
|
|||||||
err:
|
err:
|
||||||
darray_exit(&dirents);
|
darray_exit(&dirents);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reserve_old_fs_space(struct bch_fs *c,
|
static void reserve_old_fs_space(struct bch_fs *c,
|
||||||
@ -808,8 +821,8 @@ static void reserve_old_fs_space(struct bch_fs *c,
|
|||||||
update_inode(c, &dst);
|
update_inode(c, &dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
int copy_fs(struct bch_fs *c, struct copy_fs_state *s,
|
||||||
struct copy_fs_state *s, u64 reserve_start)
|
int src_fd, const char *src_path)
|
||||||
{
|
{
|
||||||
if (!S_ISDIR(xfstat(src_fd).st_mode))
|
if (!S_ISDIR(xfstat(src_fd).st_mode))
|
||||||
die("%s is not a directory", src_path);
|
die("%s is not a directory", src_path);
|
||||||
@ -820,8 +833,9 @@ void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
|||||||
struct bch_inode_unpacked root_inode;
|
struct bch_inode_unpacked root_inode;
|
||||||
int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO },
|
int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO },
|
||||||
&root_inode);
|
&root_inode);
|
||||||
|
bch_err_msg(c, ret, "looking up root directory");
|
||||||
if (ret)
|
if (ret)
|
||||||
die("error looking up root directory: %s", bch2_err_str(ret));
|
return ret;
|
||||||
|
|
||||||
if (fchdir(src_fd))
|
if (fchdir(src_fd))
|
||||||
die("fchdir error: %m");
|
die("fchdir error: %m");
|
||||||
@ -831,16 +845,41 @@ void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
|||||||
copy_xattrs(c, &root_inode, ".");
|
copy_xattrs(c, &root_inode, ".");
|
||||||
|
|
||||||
/* now, copy: */
|
/* now, copy: */
|
||||||
u64 total_wrote = 0;
|
ret = copy_dir(c, s, &root_inode, dup(src_fd), src_path);
|
||||||
copy_dir(s, c, &root_inode, dup(src_fd), src_path, reserve_start, &total_wrote);
|
bch_err_msg(c, ret, "copying filesystem");
|
||||||
|
if (ret)
|
||||||
pr_info("wrote %llu", total_wrote);
|
return ret;
|
||||||
|
|
||||||
if (s->type == BCH_MIGRATE_migrate)
|
if (s->type == BCH_MIGRATE_migrate)
|
||||||
reserve_old_fs_space(c, &root_inode, &s->extents, reserve_start);
|
reserve_old_fs_space(c, &root_inode, &s->extents, s->reserve_start);
|
||||||
|
|
||||||
update_inode(c, &root_inode);
|
update_inode(c, &root_inode);
|
||||||
|
|
||||||
darray_exit(&s->extents);
|
darray_exit(&s->extents);
|
||||||
genradix_free(&s->hardlinks);
|
genradix_free(&s->hardlinks);
|
||||||
|
|
||||||
|
CLASS(printbuf, buf)();
|
||||||
|
printbuf_tabstop_push(&buf, 24);
|
||||||
|
printbuf_tabstop_push(&buf, 16);
|
||||||
|
prt_printf(&buf, "Total files:\t%llu\r\n", s->total_files);
|
||||||
|
prt_str_indented(&buf, "Total input:\t");
|
||||||
|
prt_human_readable_u64(&buf, s->total_input);
|
||||||
|
prt_printf(&buf, "\r\n");
|
||||||
|
|
||||||
|
if (s->total_wrote) {
|
||||||
|
prt_str_indented(&buf, "Wrote:\t");
|
||||||
|
prt_human_readable_u64(&buf, s->total_wrote);
|
||||||
|
prt_printf(&buf, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->total_linked) {
|
||||||
|
prt_str(&buf, "Linked:\t");
|
||||||
|
prt_human_readable_u64(&buf, s->total_linked);
|
||||||
|
prt_printf(&buf, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
prt_newline(&buf);
|
||||||
|
|
||||||
|
fputs(buf.buf, stdout);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,13 @@ struct copy_fs_state {
|
|||||||
GENRADIX(u64) hardlinks;
|
GENRADIX(u64) hardlinks;
|
||||||
ranges extents;
|
ranges extents;
|
||||||
enum bch_migrate_type type;
|
enum bch_migrate_type type;
|
||||||
|
|
||||||
|
u64 reserve_start;
|
||||||
|
|
||||||
|
u64 total_files;
|
||||||
|
u64 total_input;
|
||||||
|
u64 total_wrote;
|
||||||
|
u64 total_linked;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -49,6 +56,6 @@ struct copy_fs_state {
|
|||||||
* In the migrate case, all the fields from `copy_fs_state` need to be
|
* In the migrate case, all the fields from `copy_fs_state` need to be
|
||||||
* initialized (`hardlinks` is initialized with zeroes).
|
* initialized (`hardlinks` is initialized with zeroes).
|
||||||
*/
|
*/
|
||||||
void copy_fs(struct bch_fs *c, int src_fd, const char *src_path,
|
int copy_fs(struct bch_fs *, struct copy_fs_state *, int, const char *);
|
||||||
struct copy_fs_state *s, u64);
|
|
||||||
#endif /* _LIBBCACHE_H */
|
#endif /* _LIBBCACHE_H */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user