diff options
-rw-r--r-- | c_src/cmd_format.c | 4 | ||||
-rw-r--r-- | c_src/cmd_image.c | 4 | ||||
-rw-r--r-- | c_src/cmd_migrate.c | 12 | ||||
-rw-r--r-- | c_src/posix_to_bcachefs.c | 117 | ||||
-rw-r--r-- | c_src/posix_to_bcachefs.h | 11 |
5 files changed, 99 insertions, 49 deletions
diff --git a/c_src/cmd_format.c b/c_src/cmd_format.c index d0c56882..d494c357 100644 --- a/c_src/cmd_format.c +++ b/c_src/cmd_format.c @@ -102,12 +102,12 @@ static const struct option format_opts[] = { }; #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 = {}; 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[]) diff --git a/c_src/cmd_image.c b/c_src/cmd_image.c index dca01825..a35ccd6f 100644 --- a/c_src/cmd_image.c +++ b/c_src/cmd_image.c @@ -273,7 +273,9 @@ static void image_create(struct bch_opt_strs fs_opt_strs, goto err; 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) printf("moving non-alloc btree to primary device\n"); diff --git a/c_src/cmd_migrate.c b/c_src/cmd_migrate.c index b4da4e5b..1b08577f 100644 --- a/c_src/cmd_migrate.c +++ b/c_src/cmd_migrate.c @@ -279,17 +279,19 @@ static int migrate_fs(const char *fs_path, .dev = stat.st_dev, .extents = extents, .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, - bucket_bytes(c->devs[0])); - BUG_ON(!reserve_start); - - copy_fs(c, fs_fd, fs_path, &s, reserve_start); + ret = copy_fs(c, &s, fs_fd, fs_path); bch2_fs_stop(c); + if (ret) + return ret; + printf("Migrate complete, running fsck:\n"); opt_set(opts, nostart, false); opt_set(opts, nochanges, true); diff --git a/c_src/posix_to_bcachefs.c b/c_src/posix_to_bcachefs.c index dfdea7ab..bcf960ac 100644 --- a/c_src/posix_to_bcachefs.c +++ b/c_src/posix_to_bcachefs.c @@ -338,10 +338,10 @@ void copy_link(struct bch_fs *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, - int src_fd, u64 src_size, - char *src_path, struct copy_fs_state *s, - u64 reserve_start) +static void link_file_data(struct bch_fs *c, + struct copy_fs_state *s, + struct bch_inode_unpacked *dst, + int src_fd, char *src_path, u64 src_size) { struct fiemap_iter iter; 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_for_each(src_fd, iter, e) { + s->total_input += e.fe_length; + u64 src_max = roundup(src_size, block_bytes(c)); 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)) || (e.fe_length & (block_bytes(c) - 1))) 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_DATA_INLINE))) { copy_data(c, dst, src_fd, e.fe_logical, - e.fe_logical + min(src_size - e.fe_logical, - e.fe_length)); + e.fe_logical + visible_len); + s->total_wrote += visible_len; continue; } /* 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, - e.fe_logical + min(src_size - e.fe_logical, - e.fe_length)); + e.fe_logical + visible_len); + s->total_wrote += visible_len; 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); link_data(c, dst, e.fe_logical, e.fe_physical, e.fe_length); + s->total_linked += e.fe_length; } 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, + struct copy_fs_state *s, subvol_inum dst_inum, struct bch_inode_unpacked *dst, int src_fd, u64 src_size, - u64 *total_wrote, struct range r) { 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) { write_data(c, dst, r.start + 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; @@ -503,10 +508,10 @@ static void copy_sync_file_range(struct bch_fs *c, } static void copy_sync_file_data(struct bch_fs *c, + struct copy_fs_state *s, subvol_inum dst_inum, struct bch_inode_unpacked *dst, - int src_fd, u64 src_size, - u64 *total_wrote) + int src_fd, u64 src_size) { 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)); } - 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; } @@ -594,6 +601,7 @@ static int recursive_remove(struct bch_fs *c, struct bch_inode_unpacked 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) return ret; @@ -619,12 +627,16 @@ static int recursive_remove(struct bch_fs *c, ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, bch2_unlink_trans(trans, dir_inum, dir, &child, &d_name, false)); + bch_err_msg(c, ret, "unlinking %s", d->d_name); if (ret) return ret; - return !child.bi_nlink - ? bch2_inode_rm(c, child_inum) - : 0; + if (!(child.bi_flags & BCH_INODE_unlinked)) + return 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, @@ -642,7 +654,7 @@ static int delete_non_matching_dirents(struct bch_fs *c, struct dirent *src_d = src_dirents.data; darray_for_each(dst_dirents, dst_d) { while (src_d < &darray_top(src_dirents) && - dirent_cmp(src_d,dst_d) < 0) + dirent_cmp(src_d, dst_d) < 0) src_d++; if (src_d == &darray_top(src_dirents) || @@ -660,16 +672,13 @@ static int delete_non_matching_dirents(struct bch_fs *c, } err: darray_exit(&dst_dirents); - bch_err_fn(c, ret); return ret; } -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, - u64 reserve_start, - u64 *total_wrote) +static int copy_dir(struct bch_fs *c, + struct copy_fs_state *s, + struct bch_inode_unpacked *dst, + int src_fd, const char *src_path) { 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) continue; + s->total_files++; + char *child_path = mprintf("%s/%s", src_path, d->d_name); 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)) { case DT_DIR: fd = xopen(d->d_name, O_RDONLY|O_NOATIME); - copy_dir(s, c, &inode, fd, child_path, - reserve_start, total_wrote); + ret = copy_dir(c, s, &inode, fd, child_path); + if (ret) + goto err; break; case DT_REG: inode.bi_size = stat.st_size; fd = xopen(d->d_name, O_RDONLY|O_NOATIME); if (s->type == BCH_MIGRATE_migrate) - link_file_data(c, &inode, fd, stat.st_size, - child_path, s, reserve_start); + link_file_data(c, s, &inode, + fd, child_path, stat.st_size); else - copy_sync_file_data(c, dst_child_inum, &inode, - fd, stat.st_size, total_wrote); + copy_sync_file_data(c, s, dst_child_inum, &inode, + fd, stat.st_size); xclose(fd); break; case DT_LNK: @@ -776,6 +788,7 @@ next: err: darray_exit(&dirents); closedir(dir); + return ret; } 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); } -void copy_fs(struct bch_fs *c, int src_fd, const char *src_path, - struct copy_fs_state *s, u64 reserve_start) +int copy_fs(struct bch_fs *c, struct copy_fs_state *s, + int src_fd, const char *src_path) { if (!S_ISDIR(xfstat(src_fd).st_mode)) 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; int ret = bch2_inode_find_by_inum(c, (subvol_inum) { 1, BCACHEFS_ROOT_INO }, &root_inode); + bch_err_msg(c, ret, "looking up root directory"); if (ret) - die("error looking up root directory: %s", bch2_err_str(ret)); + return ret; if (fchdir(src_fd)) 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, "."); /* now, copy: */ - u64 total_wrote = 0; - copy_dir(s, c, &root_inode, dup(src_fd), src_path, reserve_start, &total_wrote); - - pr_info("wrote %llu", total_wrote); + ret = copy_dir(c, s, &root_inode, dup(src_fd), src_path); + bch_err_msg(c, ret, "copying filesystem"); + if (ret) + return ret; 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); darray_exit(&s->extents); 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; } diff --git a/c_src/posix_to_bcachefs.h b/c_src/posix_to_bcachefs.h index 3ff18a44..542ae171 100644 --- a/c_src/posix_to_bcachefs.h +++ b/c_src/posix_to_bcachefs.h @@ -36,6 +36,13 @@ struct copy_fs_state { GENRADIX(u64) hardlinks; ranges extents; 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 * 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, u64); +int copy_fs(struct bch_fs *, struct copy_fs_state *, int, const char *); + #endif /* _LIBBCACHE_H */ |