Skip to content

Commit

Permalink
Merge pull request #542 from ddiss/libfuse3
Browse files Browse the repository at this point in the history
lklfuse: migrate to libfuse3
  • Loading branch information
tavip authored May 31, 2024
2 parents ab9b0d4 + fc0d27b commit 77cc0f1
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 81 deletions.
2 changes: 1 addition & 1 deletion tools/lkl/Makefile.autoconf
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ define posix_host
$(if $(filter $(1),elf64-littleaarch64),$(call aarch64_host))
$(if $(filter yes,$(dpdk)),$(call virtio_net_dpdk))
$(if $(filter yes,$(vde)),$(call virtio_net_vde))
$(if $(strip $(call find_include,fuse.h)),$(call set_autoconf_var,FUSE,y))
$(if $(strip $(call find_include,fuse3/fuse.h)),$(call set_autoconf_var,FUSE,y))
$(if $(strip $(call find_include,archive.h)),$(call set_autoconf_var,ARCHIVE,y))
$(if $(strip $(call find_include,linux/if_tun.h)),$(call set_autoconf_var,VIRTIO_NET_MACVTAP,y))
$(if $(filter $(1),elf64-x86-64-freebsd),$(call set_autoconf_var,NEEDS_LARGP,y))
Expand Down
2 changes: 1 addition & 1 deletion tools/lkl/Targets
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LDFLAGS_lib/hijack/liblkl-zpoline-$(LKL_HOST_CONFIG_POSIX) += -shared -nodefault
LDLIBS_lib/hijack/liblkl-zpoline-$(LKL_HOST_CONFIG_POSIX) += -ldl -lc

progs-$(LKL_HOST_CONFIG_FUSE) += lklfuse
LDLIBS_lklfuse-y := -lfuse
LDLIBS_lklfuse-y := -lfuse3

progs-$(LKL_HOST_CONFIG_ARCHIVE) += fs2tar
LDLIBS_fs2tar-y := -larchive
Expand Down
203 changes: 124 additions & 79 deletions tools/lkl/lklfuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <fuse/fuse_opt.h>
#include <fuse/fuse_lowlevel.h>
#define FUSE_USE_VERSION 35
#include <fuse3/fuse.h>
#include <fuse3/fuse_opt.h>
#include <fuse3/fuse_lowlevel.h>
#include <lkl.h>
#include <lkl_host.h>

#define LKLFUSE_VERSION "0.1"
#define LKLFUSE_VERSION "0.3"

struct lklfuse {
const char *file;
Expand Down Expand Up @@ -63,7 +63,7 @@ static void usage(void)
"lklfuse options:\n"
" -o log=FILE log file\n"
" -o type=fstype filesystem type\n"
" -o mb=memory in mb ammount of memory to allocate\n"
" -o mb=memory amount of memory to allocate in MB (default: 64)\n"
" -o part=parition partition to mount\n"
" -o ro open file read-only\n"
" -o opts=options mount options (use \\ to escape , and =)\n"
Expand All @@ -88,7 +88,9 @@ static int lklfuse_opt_proc(void *data, const char *arg, int key,

case KEY_HELP:
usage();
fuse_opt_add_arg(args, "-ho");
/* suppress fuse usage */
args->argv[0] = "";
fuse_opt_add_arg(args, "-h");
fuse_main(args->argc, args->argv, NULL, NULL);
exit(1);

Expand Down Expand Up @@ -124,31 +126,24 @@ static void lklfuse_xlat_stat(const struct lkl_stat *in, struct stat *st)
st->st_ctim.tv_nsec = in->st_ctime_nsec;
}

static int lklfuse_fgetattr(const char *path, struct stat *st,
struct fuse_file_info *fi)
static int lklfuse_getattr(const char *path, struct stat *st,
struct fuse_file_info *fi)
{
long ret;
struct lkl_stat lkl_stat;

ret = lkl_sys_fstat(fi->fh, &lkl_stat);
if (ret)
return ret;

lklfuse_xlat_stat(&lkl_stat, st);
return 0;
}

static int lklfuse_getattr(const char *path, struct stat *st)
{
long ret;
struct lkl_stat lkl_stat;

ret = lkl_sys_lstat(path, &lkl_stat);
if (ret)
return ret;
/*
* With nullpath_ok, path will be provided only if the struct
* fuse_file_info argument is NULL.
*/
if (fi)
ret = lkl_sys_fstat(fi->fh, &lkl_stat);
else
ret = lkl_sys_lstat(path, &lkl_stat);
if (!ret)
lklfuse_xlat_stat(&lkl_stat, st);

lklfuse_xlat_stat(&lkl_stat, st);
return 0;
return ret;
}

static int lklfuse_readlink(const char *path, char *buf, size_t len)
Expand Down Expand Up @@ -193,31 +188,56 @@ static int lklfuse_symlink(const char *oldname, const char *newname)
}


static int lklfuse_rename(const char *oldname, const char *newname)
static int lklfuse_rename(const char *oldname, const char *newname,
unsigned int flags)
{
return lkl_sys_rename(oldname, newname);
/* libfuse: *flags* may be `RENAME_EXCHANGE` or `RENAME_NOREPLACE` */
return lkl_sys_renameat2(LKL_AT_FDCWD, oldname, LKL_AT_FDCWD, newname,
flags);
}

static int lklfuse_link(const char *oldname, const char *newname)
{
return lkl_sys_link(oldname, newname);
}

static int lklfuse_chmod(const char *path, mode_t mode)
static int lklfuse_chmod(const char *path, mode_t mode,
struct fuse_file_info *fi)
{
return lkl_sys_chmod(path, mode);
}
int ret;

if (fi)
ret = lkl_sys_fchmod(fi->fh, mode);
else
ret = lkl_sys_fchmodat(LKL_AT_FDCWD, path, mode);

static int lklfuse_chown(const char *path, uid_t uid, gid_t gid)
return ret;
}

static int lklfuse_chown(const char *path, uid_t uid, gid_t gid,
struct fuse_file_info *fi)
{
return lkl_sys_fchownat(LKL_AT_FDCWD, path, uid, gid,
int ret;

if (fi)
ret = lkl_sys_fchown(fi->fh, uid, gid);
else
ret = lkl_sys_fchownat(LKL_AT_FDCWD, path, uid, gid,
LKL_AT_SYMLINK_NOFOLLOW);
return ret;
}

static int lklfuse_truncate(const char *path, off_t off)
static int lklfuse_truncate(const char *path, off_t off,
struct fuse_file_info *fi)
{
return lkl_sys_truncate(path, off);
int ret;

if (fi)
ret = lkl_sys_ftruncate(fi->fh, off);
else
ret = lkl_sys_truncate(path, off);

return ret;
}

static int lklfuse_open3(const char *path, bool create, mode_t mode,
Expand Down Expand Up @@ -397,7 +417,8 @@ static int lklfuse_opendir(const char *path, struct fuse_file_info *fi)
* Introduced in version 2.3
*/
static int lklfuse_readdir(const char *path, void *buf, fuse_fill_dir_t fill,
off_t off, struct fuse_file_info *fi)
off_t off, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{
struct lkl_dir *dir = (struct lkl_dir *)(uintptr_t)fi->fh;
struct lkl_linux_dirent64 *de;
Expand All @@ -408,7 +429,7 @@ static int lklfuse_readdir(const char *path, void *buf, fuse_fill_dir_t fill,
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;

if (fill(buf, de->d_name, &st, 0))
if (fill(buf, de->d_name, &st, 0, 0))
break;
}

Expand Down Expand Up @@ -442,17 +463,24 @@ static int lklfuse_access(const char *path, int mode)
return lkl_sys_access(path, mode);
}

static int lklfuse_utimens(const char *path, const struct timespec tv[2])
static int lklfuse_utimens(const char *path, const struct timespec tv[2],
struct fuse_file_info *fi)
{
struct lkl_timespec ts[2];

ts[0].tv_sec = tv[0].tv_sec;
ts[0].tv_nsec = tv[0].tv_nsec;
ts[1].tv_sec = tv[0].tv_sec;
ts[1].tv_nsec = tv[0].tv_nsec;

return lkl_sys_utimensat(-1, path, (struct __lkl__kernel_timespec *)ts,
LKL_AT_SYMLINK_NOFOLLOW);
int ret;
struct lkl_timespec ts[2] = {
{ .tv_sec = tv[0].tv_sec, .tv_nsec = tv[0].tv_nsec },
{ .tv_sec = tv[1].tv_sec, .tv_nsec = tv[1].tv_nsec },
};

if (fi)
ret = lkl_sys_utimensat(fi->fh, NULL,
(struct __lkl__kernel_timespec *)ts,
0);
else
ret = lkl_sys_utimensat(-1, path,
(struct __lkl__kernel_timespec *)ts,
LKL_AT_SYMLINK_NOFOLLOW);
return ret;
}

static int lklfuse_fallocate(const char *path, int mode, off_t offset,
Expand All @@ -461,10 +489,14 @@ static int lklfuse_fallocate(const char *path, int mode, off_t offset,
return lkl_sys_fallocate(fi->fh, mode, offset, len);
}

static void *lklfuse_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
{
cfg->nullpath_ok = 1;
return NULL;
}

const struct fuse_operations lklfuse_ops = {
.flag_nullpath_ok = 1,
.flag_nopath = 1,
.flag_utime_omit_ok = 1,
.init = lklfuse_init,

.getattr = lklfuse_getattr,
.readlink = lklfuse_readlink,
Expand Down Expand Up @@ -495,7 +527,6 @@ const struct fuse_operations lklfuse_ops = {
.fsyncdir = lklfuse_fsyncdir,
.access = lklfuse_access,
.create = lklfuse_create,
.fgetattr = lklfuse_fgetattr,
/* .lock, */
.utimens = lklfuse_utimens,
/* .bmap, */
Expand All @@ -511,13 +542,30 @@ static int start_lkl(void)
{
long ret;
char mpoint[32];
struct timespec walltime;
struct lkl_timespec ts;

ret = lkl_start_kernel("mem=%dM", lklfuse.mb);
if (ret) {
fprintf(stderr, "can't start kernel: %s\n", lkl_strerror(ret));
goto out;
}

/* forward host walltime to lkl */
ret = clock_gettime(CLOCK_REALTIME, &walltime);
if (ret < 0)
goto out_halt;

ts = (struct lkl_timespec){ .tv_sec = walltime.tv_sec,
.tv_nsec = walltime.tv_nsec };
ret = lkl_sys_clock_settime(LKL_CLOCK_REALTIME,
(struct __lkl__kernel_timespec *)&ts);
if (ret < 0) {
fprintf(stderr, "lkl_sys_clock_settime() failed: %s\n",
lkl_strerror(ret));
goto out_halt;
}

ret = lkl_mount_dev(lklfuse.disk_id, lklfuse.part, lklfuse.type,
lklfuse.ro ? LKL_MS_RDONLY : 0, lklfuse.opts,
mpoint, sizeof(mpoint));
Expand Down Expand Up @@ -563,11 +611,10 @@ static void stop_lkl(void)
int main(int argc, char **argv)
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_chan *ch;
struct fuse_cmdline_opts cli_opts;
struct fuse *fuse;
struct stat st;
char *mnt;
int fg, mt, ret;
int ret;

if (fuse_opt_parse(&args, &lklfuse, lklfuse_opts, lklfuse_opt_proc))
return 1;
Expand All @@ -577,12 +624,12 @@ int main(int argc, char **argv)
return 1;
}

if (fuse_parse_cmdline(&args, &mnt, &mt, &fg))
if (fuse_parse_cmdline(&args, &cli_opts))
return 1;

ret = stat(mnt, &st);
ret = stat(cli_opts.mountpoint, &st);
if (ret) {
perror(mnt);
perror(cli_opts.mountpoint);
goto out_free;
}

Expand All @@ -608,49 +655,47 @@ int main(int argc, char **argv)

lklfuse.disk_id = ret;

ch = fuse_mount(mnt, &args);
if (!ch) {
fuse = fuse_new(&args, &lklfuse_ops, sizeof(lklfuse_ops), NULL);
if (!fuse) {
ret = -1;
goto out_close_disk;
}

fuse = fuse_new(ch, &args, &lklfuse_ops, sizeof(lklfuse_ops), NULL);
if (!fuse) {
ret = -1;
goto out_fuse_unmount;
}
ret = fuse_set_signal_handlers(fuse_get_session(fuse));
if (ret < 0)
goto out_fuse_destroy;

ret = fuse_mount(fuse, cli_opts.mountpoint);
if (ret < 0)
goto out_remove_signals;

fuse_opt_free_args(&args);

if (fuse_daemonize(fg) ||
fuse_set_signal_handlers(fuse_get_session(fuse))) {
ret = -1;
goto out_fuse_destroy;
}
ret = fuse_daemonize(cli_opts.foreground);
if (ret < 0)
goto out_fuse_unmount;

ret = start_lkl();
if (ret) {
ret = -1;
goto out_remove_signals;
goto out_fuse_unmount;
}

if (mt)
if (!cli_opts.singlethread)
fprintf(stderr, "warning: multithreaded mode not supported\n");

ret = fuse_loop(fuse);

stop_lkl();

out_fuse_unmount:
fuse_unmount(fuse);

out_remove_signals:
fuse_remove_signal_handlers(fuse_get_session(fuse));

out_fuse_unmount:
if (ch)
fuse_unmount(mnt, ch);

out_fuse_destroy:
if (fuse)
fuse_destroy(fuse);
fuse_destroy(fuse);

out_lkl_cleanup:
lkl_cleanup();
Expand All @@ -659,7 +704,7 @@ int main(int argc, char **argv)
close(lklfuse.disk.fd);

out_free:
free(mnt);
free(cli_opts.mountpoint);

return ret < 0 ? 1 : 0;
}

0 comments on commit 77cc0f1

Please sign in to comment.