X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_fusemount.c;h=d81f31884cb27a2704cd898ff688fd51f5f139c5;hb=d101ad4a61ce48c498936b28eedcf0e01a568d49;hp=5418a556912f772923d6e5d1ff1de864b2e8f8c3;hpb=17a7161dbe14489c424eab4885dd706ab77dc13f;p=bcachefs-tools-debian diff --git a/cmd_fusemount.c b/cmd_fusemount.c index 5418a55..d81f318 100644 --- a/cmd_fusemount.c +++ b/cmd_fusemount.c @@ -17,10 +17,12 @@ #include "libbcachefs/btree_iter.h" #include "libbcachefs/buckets.h" #include "libbcachefs/dirent.h" +#include "libbcachefs/errcode.h" #include "libbcachefs/error.h" #include "libbcachefs/fs-common.h" #include "libbcachefs/inode.h" -#include "libbcachefs/io.h" +#include "libbcachefs/io_read.h" +#include "libbcachefs/io_write.h" #include "libbcachefs/opts.h" #include "libbcachefs/super.h" @@ -32,9 +34,18 @@ /* XXX cut and pasted from fsck.c */ #define QSTR(n) { { { .len = strlen(n) } }, .name = n } -static inline u64 map_root_ino(u64 ino) +/* used by write_aligned function for waiting on bch2_write closure */ +struct write_aligned_op_t { + struct closure cl; + + /* must be last: */ + struct bch_write_op op; +}; + + +static inline subvol_inum map_root_ino(u64 ino) { - return ino == 1 ? 4096 : ino; + return (subvol_inum) { 1, ino == 1 ? 4096 : ino }; } static inline u64 unmap_root_ino(u64 ino) @@ -91,19 +102,18 @@ static void bcachefs_fuse_destroy(void *arg) bch2_fs_stop(c); } -static void bcachefs_fuse_lookup(fuse_req_t req, fuse_ino_t dir, +static void bcachefs_fuse_lookup(fuse_req_t req, fuse_ino_t dir_ino, const char *name) { + subvol_inum dir = map_root_ino(dir_ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked bi; struct qstr qstr = QSTR(name); - u64 inum; + subvol_inum inum; int ret; fuse_log(FUSE_LOG_DEBUG, "fuse_lookup(dir=%llu name=%s)\n", - dir, name); - - dir = map_root_ino(dir); + dir.inum, name); ret = bch2_inode_find_by_inum(c, dir, &bi); if (ret) { @@ -113,8 +123,8 @@ static void bcachefs_fuse_lookup(fuse_req_t req, fuse_ino_t dir, struct bch_hash_info hash_info = bch2_hash_info_init(c, &bi); - inum = bch2_dirent_lookup(c, dir, &hash_info, &qstr); - if (!inum) { + ret = bch2_dirent_lookup(c, dir, &hash_info, &qstr, &inum); + if (ret) { struct fuse_entry_param e = { .attr_timeout = DBL_MAX, .entry_timeout = DBL_MAX, @@ -138,20 +148,17 @@ err: fuse_reply_err(req, -ret); } -static void bcachefs_fuse_getattr(fuse_req_t req, fuse_ino_t inum, +static void bcachefs_fuse_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { + subvol_inum inum = map_root_ino(ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked bi; struct stat attr; - int ret; - - fuse_log(FUSE_LOG_DEBUG, "fuse_getattr(inum=%llu)\n", - inum); - inum = map_root_ino(inum); + fuse_log(FUSE_LOG_DEBUG, "fuse_getattr(inum=%llu)\n", inum.inum); - ret = bch2_inode_find_by_inum(c, inum, &bi); + int ret = bch2_inode_find_by_inum(c, inum, &bi); if (ret) { fuse_log(FUSE_LOG_DEBUG, "fuse_getattr error %i\n", ret); fuse_reply_err(req, -ret); @@ -164,29 +171,27 @@ static void bcachefs_fuse_getattr(fuse_req_t req, fuse_ino_t inum, fuse_reply_attr(req, &attr, DBL_MAX); } -static void bcachefs_fuse_setattr(fuse_req_t req, fuse_ino_t inum, +static void bcachefs_fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi) { struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked inode_u; - struct btree_trans trans; - struct btree_iter *iter; + struct btree_trans *trans; + struct btree_iter iter; u64 now; int ret; - fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_setattr(%llu, %x)\n", - inum, to_set); + subvol_inum inum = map_root_ino(ino); - inum = map_root_ino(inum); + fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_setattr(%llu, %x)\n", inum.inum, to_set); - bch2_trans_init(&trans, c, 0, 0); + trans = bch2_trans_get(c); retry: - bch2_trans_begin(&trans); + bch2_trans_begin(trans); now = bch2_current_time(c); - iter = bch2_inode_peek(&trans, &inode_u, inum, BTREE_ITER_INTENT); - ret = PTR_ERR_OR_ZERO(iter); + ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_INTENT); if (ret) goto err; @@ -208,15 +213,15 @@ retry: inode_u.bi_mtime = now; /* TODO: CTIME? */ - ret = bch2_inode_write(&trans, iter, &inode_u) ?: - bch2_trans_commit(&trans, NULL, NULL, - BTREE_INSERT_ATOMIC| - BTREE_INSERT_NOFAIL); + ret = bch2_inode_write(trans, &iter, &inode_u) ?: + bch2_trans_commit(trans, NULL, NULL, + BCH_TRANS_COMMIT_no_enospc); err: + bch2_trans_iter_exit(trans, &iter); if (ret == -EINTR) goto retry; - bch2_trans_exit(&trans); + bch2_trans_put(trans); if (!ret) { *attr = inode_to_stat(c, &inode_u); @@ -226,34 +231,37 @@ err: } } -static int do_create(struct bch_fs *c, u64 dir, +static int do_create(struct bch_fs *c, subvol_inum dir, const char *name, mode_t mode, dev_t rdev, struct bch_inode_unpacked *new_inode) { struct qstr qstr = QSTR(name); struct bch_inode_unpacked dir_u; - - dir = map_root_ino(dir); + uid_t uid = 0; + gid_t gid = 0; bch2_inode_init_early(c, new_inode); - return bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC, - bch2_create_trans(&trans, + return bch2_trans_do(c, NULL, NULL, 0, + bch2_create_trans(trans, dir, &dir_u, new_inode, &qstr, - 0, 0, mode, rdev, NULL, NULL)); + uid, gid, mode, rdev, NULL, NULL, + (subvol_inum) { 0 }, 0)); } -static void bcachefs_fuse_mknod(fuse_req_t req, fuse_ino_t dir, +static void bcachefs_fuse_mknod(fuse_req_t req, fuse_ino_t dir_ino, const char *name, mode_t mode, dev_t rdev) { + subvol_inum dir = map_root_ino(dir_ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked new_inode; int ret; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_mknod(%llu, %s, %x, %x)\n", - dir, name, mode, rdev); + dir.inum, name, mode, rdev); + ret = do_create(c, dir, name, mode, rdev, &new_inode); if (ret) goto err; @@ -277,21 +285,20 @@ static void bcachefs_fuse_mkdir(fuse_req_t req, fuse_ino_t dir, bcachefs_fuse_mknod(req, dir, name, mode, 0); } -static void bcachefs_fuse_unlink(fuse_req_t req, fuse_ino_t dir, +static void bcachefs_fuse_unlink(fuse_req_t req, fuse_ino_t dir_ino, const char *name) { struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked dir_u, inode_u; struct qstr qstr = QSTR(name); - int ret; + subvol_inum dir = map_root_ino(dir_ino); - fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_unlink(%llu, %s)\n", dir, name); + fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_unlink(%llu, %s)\n", dir.inum, name); - dir = map_root_ino(dir); - - ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC|BTREE_INSERT_NOFAIL, - bch2_unlink_trans(&trans, dir, &dir_u, - &inode_u, &qstr)); + int ret = bch2_trans_do(c, NULL, NULL, + BCH_TRANS_COMMIT_no_enospc, + bch2_unlink_trans(trans, dir, &dir_u, + &inode_u, &qstr, false)); fuse_reply_err(req, -ret); } @@ -301,14 +308,12 @@ static void bcachefs_fuse_rmdir(fuse_req_t req, fuse_ino_t dir, { fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_rmdir(%llu, %s)\n", dir, name); - dir = map_root_ino(dir); - bcachefs_fuse_unlink(req, dir, name); } static void bcachefs_fuse_rename(fuse_req_t req, - fuse_ino_t src_dir, const char *srcname, - fuse_ino_t dst_dir, const char *dstname, + fuse_ino_t src_dir_ino, const char *srcname, + fuse_ino_t dst_dir_ino, const char *dstname, unsigned flags) { struct bch_fs *c = fuse_req_userdata(req); @@ -316,18 +321,17 @@ static void bcachefs_fuse_rename(fuse_req_t req, struct bch_inode_unpacked src_inode_u, dst_inode_u; struct qstr dst_name = QSTR(srcname); struct qstr src_name = QSTR(dstname); + subvol_inum src_dir = map_root_ino(src_dir_ino); + subvol_inum dst_dir = map_root_ino(dst_dir_ino); int ret; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_rename(%llu, %s, %llu, %s, %x)\n", - src_dir, srcname, dst_dir, dstname, flags); - - src_dir = map_root_ino(src_dir); - dst_dir = map_root_ino(dst_dir); + src_dir.inum, srcname, dst_dir.inum, dstname, flags); /* XXX handle overwrites */ - ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC, - bch2_rename_trans(&trans, + ret = bch2_trans_do(c, NULL, NULL, 0, + bch2_rename_trans(trans, src_dir, &src_dir_u, dst_dir, &dst_dir_u, &src_inode_u, &dst_inode_u, @@ -337,22 +341,22 @@ static void bcachefs_fuse_rename(fuse_req_t req, fuse_reply_err(req, -ret); } -static void bcachefs_fuse_link(fuse_req_t req, fuse_ino_t inum, - fuse_ino_t newparent, const char *newname) +static void bcachefs_fuse_link(fuse_req_t req, fuse_ino_t ino, + fuse_ino_t newparent_ino, const char *newname) { struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked dir_u, inode_u; struct qstr qstr = QSTR(newname); + subvol_inum newparent = map_root_ino(newparent_ino); + subvol_inum inum = map_root_ino(ino); int ret; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_link(%llu, %llu, %s)\n", - inum, newparent, newname); - - newparent = map_root_ino(newparent); + inum.inum, newparent.inum, newname); - ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC, - bch2_link_trans(&trans, newparent, - inum, &dir_u, &inode_u, &qstr)); + ret = bch2_trans_do(c, NULL, NULL, 0, + bch2_link_trans(trans, newparent, &dir_u, + inum, &inode_u, &qstr)); if (!ret) { struct fuse_entry_param e = inode_to_entry(c, &inode_u); @@ -375,22 +379,20 @@ static void bcachefs_fuse_open(fuse_req_t req, fuse_ino_t inum, static void userbio_init(struct bio *bio, struct bio_vec *bv, void *buf, size_t size) { - bio_init(bio, bv, 1); + bio_init(bio, NULL, bv, 1, 0); bio->bi_iter.bi_size = size; bv->bv_page = buf; bv->bv_len = size; bv->bv_offset = 0; } -static int get_inode_io_opts(struct bch_fs *c, u64 inum, - struct bch_io_opts *opts) +static int get_inode_io_opts(struct bch_fs *c, subvol_inum inum, struct bch_io_opts *opts) { struct bch_inode_unpacked inode; if (bch2_inode_find_by_inum(c, inum, &inode)) return -EINVAL; - *opts = bch2_opts_to_inode_opts(c->opts); - bch2_io_opts_apply(opts, bch2_inode_opts_get(&inode)); + bch2_inode_opts_get(opts, c, &inode); return 0; } @@ -399,6 +401,14 @@ static void bcachefs_fuse_read_endio(struct bio *bio) closure_put(bio->bi_private); } + +static void bcachefs_fuse_write_endio(struct bch_write_op *op) +{ + struct write_aligned_op_t *w = container_of(op,struct write_aligned_op_t,op); + closure_put(&w->cl); +} + + struct fuse_align_io { off_t start; size_t pad_start; @@ -448,7 +458,7 @@ static size_t align_fix_up_bytes(const struct fuse_align_io *align, /* * Read aligned data. */ -static int read_aligned(struct bch_fs *c, fuse_ino_t inum, size_t aligned_size, +static int read_aligned(struct bch_fs *c, subvol_inum inum, size_t aligned_size, off_t aligned_offset, void *buf) { BUG_ON(aligned_size & (block_bytes(c) - 1)); @@ -478,10 +488,11 @@ static int read_aligned(struct bch_fs *c, fuse_ino_t inum, size_t aligned_size, return -blk_status_to_errno(rbio.bio.bi_status); } -static void bcachefs_fuse_read(fuse_req_t req, fuse_ino_t inum, +static void bcachefs_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi) { + subvol_inum inum = map_root_ino(ino); struct bch_fs *c = fuse_req_userdata(req); fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_read(%llu, %zd, %lld)\n", @@ -520,88 +531,95 @@ static void bcachefs_fuse_read(fuse_req_t req, fuse_ino_t inum, free(buf); } -static int inode_update_times(struct bch_fs *c, fuse_ino_t inum) +static int inode_update_times(struct bch_fs *c, subvol_inum inum) { - struct btree_trans trans; - struct btree_iter *iter; + struct btree_trans *trans; + struct btree_iter iter; struct bch_inode_unpacked inode_u; int ret = 0; u64 now; - bch2_trans_init(&trans, c, 0, 0); + trans = bch2_trans_get(c); retry: - bch2_trans_begin(&trans); + bch2_trans_begin(trans); now = bch2_current_time(c); - iter = bch2_inode_peek(&trans, &inode_u, inum, BTREE_ITER_INTENT); - ret = PTR_ERR_OR_ZERO(iter); + ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_INTENT); if (ret) goto err; inode_u.bi_mtime = now; inode_u.bi_ctime = now; - ret = bch2_inode_write(&trans, iter, &inode_u); + ret = bch2_inode_write(trans, &iter, &inode_u); if (ret) goto err; - ret = bch2_trans_commit(&trans, NULL, NULL, - BTREE_INSERT_ATOMIC|BTREE_INSERT_NOFAIL); - + ret = bch2_trans_commit(trans, NULL, NULL, + BCH_TRANS_COMMIT_no_enospc); err: + bch2_trans_iter_exit(trans, &iter); if (ret == -EINTR) goto retry; - bch2_trans_exit(&trans); + bch2_trans_put(trans); return ret; } -static int write_aligned(struct bch_fs *c, fuse_ino_t inum, +static int write_aligned(struct bch_fs *c, subvol_inum inum, struct bch_io_opts io_opts, void *buf, size_t aligned_size, off_t aligned_offset, off_t new_i_size, size_t *written_out) { - struct bch_write_op op = { 0 }; + + struct write_aligned_op_t w = { 0 } +; + struct bch_write_op *op = &w.op; struct bio_vec bv; - struct closure cl; BUG_ON(aligned_size & (block_bytes(c) - 1)); BUG_ON(aligned_offset & (block_bytes(c) - 1)); *written_out = 0; - closure_init_stack(&cl); + closure_init_stack(&w.cl); - bch2_write_op_init(&op, c, io_opts); /* XXX reads from op?! */ - op.write_point = writepoint_hashed(0); - op.nr_replicas = io_opts.data_replicas; - op.target = io_opts.foreground_target; - op.pos = POS(inum, aligned_offset >> 9); - op.new_i_size = new_i_size; + bch2_write_op_init(op, c, io_opts); /* XXX reads from op?! */ + op->write_point = writepoint_hashed(0); + op->nr_replicas = io_opts.data_replicas; + op->target = io_opts.foreground_target; + op->subvol = inum.subvol; + op->pos = POS(inum.inum, aligned_offset >> 9); + op->new_i_size = new_i_size; + op->end_io = bcachefs_fuse_write_endio; - userbio_init(&op.wbio.bio, &bv, buf, aligned_size); - bio_set_op_attrs(&op.wbio.bio, REQ_OP_WRITE, REQ_SYNC); + userbio_init(&op->wbio.bio, &bv, buf, aligned_size); + bio_set_op_attrs(&op->wbio.bio, REQ_OP_WRITE, REQ_SYNC); - if (bch2_disk_reservation_get(c, &op.res, aligned_size >> 9, - op.nr_replicas, 0)) { + if (bch2_disk_reservation_get(c, &op->res, aligned_size >> 9, + op->nr_replicas, 0)) { /* XXX: use check_range_allocated like dio write path */ return -ENOSPC; } - closure_call(&op.cl, bch2_write, NULL, &cl); - closure_sync(&cl); + closure_get(&w.cl); + + closure_call(&op->cl, bch2_write, NULL, NULL); + + closure_sync(&w.cl); - if (!op.error) - *written_out = op.written << 9; + if (!op->error) + *written_out = op->written << 9; - return op.error; + return op->error; } -static void bcachefs_fuse_write(fuse_req_t req, fuse_ino_t inum, +static void bcachefs_fuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + subvol_inum inum = map_root_ino(ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_io_opts io_opts; size_t aligned_written; @@ -686,24 +704,23 @@ err: } static void bcachefs_fuse_symlink(fuse_req_t req, const char *link, - fuse_ino_t dir, const char *name) + fuse_ino_t dir_ino, const char *name) { + subvol_inum dir = map_root_ino(dir_ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked new_inode; size_t link_len = strlen(link); int ret; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_symlink(%s, %llu, %s)\n", - link, dir, name); - - dir = map_root_ino(dir); + link, dir.inum, name); ret = do_create(c, dir, name, S_IFLNK|S_IRWXUGO, 0, &new_inode); if (ret) goto err; struct bch_io_opts io_opts; - ret = get_inode_io_opts(c, new_inode.bi_inum, &io_opts); + ret = get_inode_io_opts(c, dir, &io_opts); if (ret) goto err; @@ -715,8 +732,10 @@ static void bcachefs_fuse_symlink(fuse_req_t req, const char *link, memset(aligned_buf, 0, align.size); memcpy(aligned_buf, link, link_len); /* already terminated */ + subvol_inum inum = (subvol_inum) { dir.subvol, new_inode.bi_inum }; + size_t aligned_written; - ret = write_aligned(c, new_inode.bi_inum, io_opts, aligned_buf, + ret = write_aligned(c, inum, io_opts, aligned_buf, align.size, align.start, link_len + 1, &aligned_written); free(aligned_buf); @@ -727,7 +746,7 @@ static void bcachefs_fuse_symlink(fuse_req_t req, const char *link, size_t written = align_fix_up_bytes(&align, aligned_written); BUG_ON(written != link_len + 1); // TODO: handle short - ret = inode_update_times(c, new_inode.bi_inum); + ret = inode_update_times(c, inum); if (ret) goto err; @@ -741,12 +760,13 @@ err: fuse_reply_err(req, -ret); } -static void bcachefs_fuse_readlink(fuse_req_t req, fuse_ino_t inum) +static void bcachefs_fuse_readlink(fuse_req_t req, fuse_ino_t ino) { + subvol_inum inum = map_root_ino(ino); struct bch_fs *c = fuse_req_userdata(req); char *buf = NULL; - fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_readlink(%llu)\n", inum); + fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_readlink(%llu)\n", inum.inum); struct bch_inode_unpacked bi; int ret = bch2_inode_find_by_inum(c, inum, &bi); @@ -898,10 +918,11 @@ static bool handle_dots(struct fuse_dir_context *ctx, fuse_ino_t dir) return true; } -static void bcachefs_fuse_readdir(fuse_req_t req, fuse_ino_t dir, +static void bcachefs_fuse_readdir(fuse_req_t req, fuse_ino_t dir_ino, size_t size, off_t off, struct fuse_file_info *fi) { + subvol_inum dir = map_root_ino(dir_ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked bi; char *buf = calloc(size, 1); @@ -915,9 +936,7 @@ static void bcachefs_fuse_readdir(fuse_req_t req, fuse_ino_t dir, int ret = 0; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_readdir(dir=%llu, size=%zu, " - "off=%lld)\n", dir, size, off); - - dir = map_root_ino(dir); + "off=%lld)\n", dir.inum, size, off); ret = bch2_inode_find_by_inum(c, dir, &bi); if (ret) @@ -928,7 +947,7 @@ static void bcachefs_fuse_readdir(fuse_req_t req, fuse_ino_t dir, goto reply; } - if (!handle_dots(&ctx, dir)) + if (!handle_dots(&ctx, dir.inum)) goto reply; ret = bch2_readdir(c, dir, &ctx.ctx); @@ -1012,16 +1031,17 @@ static void bcachefs_fuse_removexattr(fuse_req_t req, fuse_ino_t inum, } #endif -static void bcachefs_fuse_create(fuse_req_t req, fuse_ino_t dir, +static void bcachefs_fuse_create(fuse_req_t req, fuse_ino_t dir_ino, const char *name, mode_t mode, struct fuse_file_info *fi) { + subvol_inum dir = map_root_ino(dir_ino); struct bch_fs *c = fuse_req_userdata(req); struct bch_inode_unpacked new_inode; int ret; fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_create(%llu, %s, %x)\n", - dir, name, mode); + dir.inum, name, mode); ret = do_create(c, dir, name, mode, 0, &new_inode); if (ret) @@ -1032,7 +1052,6 @@ static void bcachefs_fuse_create(fuse_req_t req, fuse_ino_t dir, return; err: fuse_reply_err(req, -ret); - } #if 0 @@ -1222,6 +1241,17 @@ int cmd_fusemount(int argc, char *argv[]) } tokenize_devices(&ctx); + struct printbuf fsname = PRINTBUF; + prt_printf(&fsname, "fsname="); + for (i = 0; i < ctx.nr_devices; ++i) { + if (i) + prt_str(&fsname, ":"); + prt_str(&fsname, ctx.devices[i]); + } + + fuse_opt_add_arg(&args, "-o"); + fuse_opt_add_arg(&args, fsname.buf); + /* Open bch */ printf("Opening bcachefs filesystem on:\n"); for (i = 0; i < ctx.nr_devices; ++i) @@ -1230,7 +1260,7 @@ int cmd_fusemount(int argc, char *argv[]) c = bch2_fs_open(ctx.devices, ctx.nr_devices, bch_opts); if (IS_ERR(c)) die("error opening %s: %s", ctx.devices_str, - strerror(-PTR_ERR(c))); + bch2_err_str(PTR_ERR(c))); /* Fuse */ struct fuse_session *se = @@ -1248,6 +1278,11 @@ int cmd_fusemount(int argc, char *argv[]) /* This print statement is a trigger for tests. */ printf("Fuse mount initialized.\n"); + if (fuse_opts.foreground == 0){ + printf("Fuse forcing to foreground mode, due gcc constructors usage.\n"); + fuse_opts.foreground = 1; + } + fuse_daemonize(fuse_opts.foreground); ret = fuse_session_loop(se);