Skip to content

Commit 699f87c

Browse files
authored
Merge pull request #545 from ddiss/lklfuse_vfs_open_flags
Lklfuse: vfs mount and open flags
2 parents 7f7bc5f + b42cf5f commit 699f87c

File tree

1 file changed

+147
-2
lines changed

1 file changed

+147
-2
lines changed

tools/lkl/lklfuse.c

+147-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#define _GNU_SOURCE
3+
#include <fcntl.h>
14
#include <stdbool.h>
25
#include <stddef.h>
36
#include <stdio.h>
@@ -50,6 +53,8 @@ static struct fuse_opt lklfuse_opts[] = {
5053
FUSE_OPT_END
5154
};
5255

56+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
57+
5358
static void usage(void)
5459
{
5560
printf(
@@ -255,8 +260,39 @@ static int lklfuse_open3(const char *path, bool create, mode_t mode,
255260
else
256261
return -EINVAL;
257262

263+
/*
264+
* XXX see rules in fuse3/fuse.h:
265+
* Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be filtered out /
266+
* handled by FUSE kernel...
267+
*/
258268
if (create)
259269
flags |= LKL_O_CREAT;
270+
if (fi->flags & O_TRUNC)
271+
flags |= LKL_O_TRUNC;
272+
if (fi->flags & O_APPEND)
273+
flags |= LKL_O_APPEND;
274+
if (fi->flags & O_NONBLOCK)
275+
flags |= LKL_O_NONBLOCK;
276+
if (fi->flags & O_DSYNC)
277+
flags |= LKL_O_DSYNC;
278+
if (fi->flags & O_DIRECT)
279+
flags |= LKL_O_DIRECT;
280+
if (fi->flags & O_LARGEFILE)
281+
flags |= LKL_O_LARGEFILE;
282+
if (fi->flags & O_DIRECTORY)
283+
flags |= LKL_O_DIRECTORY;
284+
if (fi->flags & O_NOFOLLOW)
285+
flags |= LKL_O_NOFOLLOW;
286+
if (fi->flags & O_NOATIME)
287+
flags |= LKL_O_NOATIME;
288+
if (fi->flags & O_CLOEXEC)
289+
flags |= LKL_O_CLOEXEC;
290+
if (fi->flags & O_SYNC)
291+
flags |= LKL_O_SYNC;
292+
if (fi->flags & O_PATH)
293+
flags |= LKL_O_PATH;
294+
if (fi->flags & O_TMPFILE)
295+
flags |= LKL_O_TMPFILE;
260296

261297
ret = lkl_sys_open(path, flags, mode);
262298
if (ret < 0)
@@ -545,12 +581,122 @@ const struct fuse_operations lklfuse_ops = {
545581
.fallocate = lklfuse_fallocate,
546582
};
547583

584+
static int lklfuse_parse_vfs_flags(bool ro, const char *opts, int *flags,
585+
char *remain, size_t remlen)
586+
{
587+
size_t optslen;
588+
char tokbuf[4096];
589+
char *tb = tokbuf;
590+
char *tok;
591+
char *saveptr = NULL;
592+
/* we could consider using libmount for this mapping */
593+
struct flagmap {
594+
const char *opt;
595+
int flag;
596+
bool invert;
597+
} map[] = {
598+
{ "ro", LKL_MS_RDONLY },
599+
{ "nosuid", LKL_MS_NOSUID },
600+
{ "nodev", LKL_MS_NODEV },
601+
{ "noexec", LKL_MS_NOEXEC },
602+
{ "sync", LKL_MS_SYNCHRONOUS },
603+
{ "remount", LKL_MS_REMOUNT },
604+
{ "dirsync", LKL_MS_DIRSYNC },
605+
{ "nosymfollow", LKL_MS_NOSYMFOLLOW },
606+
{ "noatime", LKL_MS_NOATIME },
607+
{ "nodiratime", LKL_MS_NODIRATIME },
608+
{ "bind", LKL_MS_BIND },
609+
{ "rbind", LKL_MS_BIND | LKL_MS_REC },
610+
{ "move", LKL_MS_MOVE },
611+
{ "silent", LKL_MS_SILENT },
612+
613+
{ "relatime", LKL_MS_RELATIME },
614+
{ "iversion", LKL_MS_I_VERSION },
615+
{ "strictatime", LKL_MS_STRICTATIME },
616+
{ "lazytime", LKL_MS_LAZYTIME },
617+
618+
/* opts below aren't passed to external mount.type helpers */
619+
{ "unbindable", LKL_MS_UNBINDABLE },
620+
{ "runbindable", LKL_MS_UNBINDABLE | LKL_MS_REC },
621+
{ "private", LKL_MS_PRIVATE },
622+
{ "rprivate", LKL_MS_PRIVATE | LKL_MS_REC },
623+
{ "slave", LKL_MS_SLAVE },
624+
{ "rslave", LKL_MS_SLAVE | LKL_MS_REC },
625+
{ "shared", LKL_MS_SHARED },
626+
{ "rshared", LKL_MS_SHARED | LKL_MS_REC },
627+
628+
/* opts below invert flags */
629+
{ "rw", LKL_MS_RDONLY, true },
630+
{ "suid", LKL_MS_NOSUID, true },
631+
{ "dev", LKL_MS_NODEV, true },
632+
{ "exec", LKL_MS_NOEXEC, true },
633+
{ "async", LKL_MS_SYNCHRONOUS, true },
634+
{ "symfollow", LKL_MS_NOSYMFOLLOW, true },
635+
{ "atime", LKL_MS_NOATIME, true },
636+
{ "diratime", LKL_MS_NODIRATIME, true },
637+
{ "loud", LKL_MS_SILENT, true },
638+
{ "norelatime", LKL_MS_RELATIME, true },
639+
{ "noiversion", LKL_MS_I_VERSION, true },
640+
{ "nostrictatime", LKL_MS_STRICTATIME, true },
641+
{ "nolazytime", LKL_MS_LAZYTIME, true },
642+
};
643+
*flags = ro ? LKL_MS_RDONLY : 0;
644+
645+
optslen = opts ? strlen(opts) : 0;
646+
/* need enough space in @remain to at most pass through all options */
647+
if (optslen >= remlen || optslen >= sizeof(tokbuf))
648+
return -EINVAL;
649+
650+
*remain = '\0';
651+
if (optslen == 0)
652+
return 0;
653+
654+
strncpy(tokbuf, opts, sizeof(tokbuf));
655+
/*
656+
* '\,' and '\=' escapes for mount options provided via -o opts=... are
657+
* removed by libfuse, so we just need to map and remove any VFS flags.
658+
*/
659+
while ((tok = strtok_r(tb, ",", &saveptr)) != NULL) {
660+
size_t i;
661+
662+
tb = NULL;
663+
for (i = 0; i < ARRAY_SIZE(map); i++) {
664+
if (strcmp(tok, map[i].opt))
665+
continue;
666+
if (map[i].invert)
667+
*flags &= ~map[i].flag;
668+
else
669+
*flags |= map[i].flag;
670+
break;
671+
}
672+
/* opts mapped to a flag shouldn't be retained */
673+
if (i < ARRAY_SIZE(map))
674+
continue;
675+
676+
if (*remain != '\0')
677+
strcat(remain, ",");
678+
strcat(remain, tok);
679+
}
680+
681+
return 0;
682+
}
683+
548684
static int start_lkl(void)
549685
{
550686
long ret;
551687
char mpoint[32];
552688
struct timespec walltime;
553689
struct lkl_timespec ts;
690+
int mount_flags = 0;
691+
char remaining_mopts[4096] = { 0 };
692+
693+
ret = lklfuse_parse_vfs_flags(lklfuse.ro, lklfuse.opts, &mount_flags,
694+
remaining_mopts, sizeof(remaining_mopts));
695+
if (ret < 0) {
696+
fprintf(stderr, "failed to parse mount flags: %s\n",
697+
lklfuse.opts);
698+
goto out;
699+
}
554700

555701
ret = lkl_start_kernel("mem=%dM", lklfuse.mb);
556702
if (ret) {
@@ -574,9 +720,8 @@ static int start_lkl(void)
574720
}
575721

576722
ret = lkl_mount_dev(lklfuse.disk_id, lklfuse.part, lklfuse.type,
577-
lklfuse.ro ? LKL_MS_RDONLY : 0, lklfuse.opts,
723+
mount_flags, remaining_mopts,
578724
mpoint, sizeof(mpoint));
579-
580725
if (ret) {
581726
fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret));
582727
goto out_halt;

0 commit comments

Comments
 (0)