Skip to content

Commit d46a42c

Browse files
committed
subsys/fs/fuse: Support using libfuse3
Support using FUSE v3, instead of FUSE v2. FUSE v3 has been out for a couple of years now, so most distributions have it. But note the FUSE library (and its v3 branch) is currently unmaintained, and older distributions do not ship it. Some Linux distros have transitioned their packages away from fuse2. Which results in less atention in these distros to fuse2, and therefore a higher likelyhood that there would be distribution issues with the corresponding packages. There is also some likelihood the fuse2 packages may be eventually droped by some of these. So let's support either version, with a kconfig adapting to either API and their quirks. Note that both the fuse2 and fuse3 library code have quite a few sideeffects on the process that uses it. By now we continue defaulting to fuse2 as it is the most common. But users can select to use the v3 if they have an issue w v2 or want to start trying out using v3. Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
1 parent 94040be commit d46a42c

File tree

3 files changed

+118
-7
lines changed

3 files changed

+118
-7
lines changed

subsys/fs/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ add_subdirectory_ifdef(CONFIG_ZMS ./zms)
3636
if(CONFIG_FUSE_FS_ACCESS)
3737
zephyr_library_named(FS_FUSE)
3838
find_package(PkgConfig REQUIRED)
39-
pkg_search_module(FUSE REQUIRED fuse)
39+
if (CONFIG_FUSE_LIBRARY_V3)
40+
pkg_search_module(FUSE REQUIRED fuse3)
41+
target_compile_options(native_simulator INTERFACE "-DCONFIG_FUSE_LIBRARY_V3")
42+
else()
43+
pkg_search_module(FUSE REQUIRED fuse)
44+
endif()
4045
list(TRANSFORM FUSE_INCLUDE_DIRS PREPEND "-I")
4146
target_compile_options(native_simulator INTERFACE ${FUSE_INCLUDE_DIRS})
4247
list(TRANSFORM FUSE_LIBRARIES PREPEND "-l")

subsys/fs/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,23 @@ config FUSE_FS_ACCESS
106106
help
107107
Expose file system partitions to the host system through FUSE.
108108

109+
choice FUSE_LIBRARY_VERSION
110+
prompt "Host FUSE library version"
111+
depends on FUSE_FS_ACCESS
112+
default FUSE_LIBRARY_V2
113+
114+
config FUSE_LIBRARY_V2
115+
bool "Use libfuse(2)"
116+
help
117+
Use v2 of the host FUSE library.
118+
119+
config FUSE_LIBRARY_V3
120+
bool "Use libfuse3"
121+
help
122+
Use the host fuse3 library. This may not be available in older distributions.
123+
124+
endchoice
125+
109126
endif # FILE_SYSTEM
110127

111128
if FILE_SYSTEM_LIB_LINK

subsys/fs/fuse_fs_access_bottom.c

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8+
#if defined(CONFIG_FUSE_LIBRARY_V3)
9+
#define FUSE_USE_VERSION 30
10+
#else
811
#define FUSE_USE_VERSION 26
12+
#endif
913

1014
#undef _XOPEN_SOURCE
1115
#define _XOPEN_SOURCE 700
@@ -40,6 +44,9 @@
4044

4145
static pthread_t fuse_thread;
4246
static struct ffa_op_callbacks *op_callbacks;
47+
#if defined(CONFIG_FUSE_LIBRARY_V3)
48+
static sem_t fuse_started; /* semaphore to signal fuse_main has started */
49+
#endif
4350

4451
/* Pending operation the bottom/fuse thread is queuing into the Zephyr thread */
4552
struct {
@@ -197,8 +204,14 @@ static bool is_mount_point(const char *path)
197204
return strcmp(dirname(dir_path), "/") == 0;
198205
}
199206

207+
#if defined(CONFIG_FUSE_LIBRARY_V3)
208+
static int fuse_fs_access_getattr(const char *path, struct stat *st, struct fuse_file_info *fi)
209+
{
210+
NSI_ARG_UNUSED(fi);
211+
#else
200212
static int fuse_fs_access_getattr(const char *path, struct stat *st)
201213
{
214+
#endif
202215
struct ffa_dirent entry;
203216
int err;
204217

@@ -266,8 +279,13 @@ static int fuse_fs_access_readmount(void *buf, fuse_fill_dir_t filler)
266279
st.st_blksize = 0;
267280
st.st_blocks = 0;
268281

282+
#if defined(CONFIG_FUSE_LIBRARY_V3)
283+
filler(buf, ".", &st, 0, 0);
284+
filler(buf, "..", NULL, 0, 0);
285+
#else
269286
filler(buf, ".", &st, 0);
270287
filler(buf, "..", NULL, 0);
288+
#endif
271289

272290
do {
273291
struct op_args_readmount args;
@@ -282,7 +300,11 @@ static int fuse_fs_access_readmount(void *buf, fuse_fill_dir_t filler)
282300
break;
283301
}
284302

303+
#if defined(CONFIG_FUSE_LIBRARY_V3)
304+
filler(buf, &mnt_name[1], &st, 0, 0);
305+
#else
285306
filler(buf, &mnt_name[1], &st, 0);
307+
#endif
286308

287309
} while (true);
288310

@@ -293,9 +315,16 @@ static int fuse_fs_access_readmount(void *buf, fuse_fill_dir_t filler)
293315
return err;
294316
}
295317

318+
#if defined(CONFIG_FUSE_LIBRARY_V3)
319+
static int fuse_fs_access_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t off,
320+
struct fuse_file_info *fi, enum fuse_readdir_flags flags)
321+
{
322+
NSI_ARG_UNUSED(flags);
323+
#else
296324
static int fuse_fs_access_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t off,
297325
struct fuse_file_info *fi)
298326
{
327+
#endif
299328
NSI_ARG_UNUSED(off);
300329
NSI_ARG_UNUSED(fi);
301330

@@ -345,8 +374,13 @@ static int fuse_fs_access_readdir(const char *path, void *buf, fuse_fill_dir_t f
345374
st.st_blksize = 0;
346375
st.st_blocks = 0;
347376

377+
#if defined(CONFIG_FUSE_LIBRARY_V3)
378+
filler(buf, ".", &st, 0, 0);
379+
filler(buf, "..", &st, 0, 0);
380+
#else
348381
filler(buf, ".", &st, 0);
349382
filler(buf, "..", &st, 0);
383+
#endif
350384

351385
do {
352386
err = queue_op(OP_READDIR_READ_NEXT, (void *)&entry);
@@ -366,7 +400,13 @@ static int fuse_fs_access_readdir(const char *path, void *buf, fuse_fill_dir_t f
366400
st.st_size = entry.size;
367401
}
368402

369-
if (filler(buf, entry.name, &st, 0)) {
403+
#if defined(CONFIG_FUSE_LIBRARY_V3)
404+
bool full = filler(buf, entry.name, &st, 0, 0);
405+
#else
406+
bool full = filler(buf, entry.name, &st, 0);
407+
#endif
408+
409+
if (full) {
370410
break;
371411
}
372412
} while (1);
@@ -468,6 +508,7 @@ static int fuse_fs_access_write(const char *path, const char *buf, size_t size,
468508
return -nsi_errno_from_mid(err);
469509
}
470510

511+
#if !defined(CONFIG_FUSE_LIBRARY_V3)
471512
static int fuse_fs_access_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
472513
{
473514
struct op_args_ftruncate args;
@@ -486,9 +527,16 @@ static int fuse_fs_access_ftruncate(const char *path, off_t size, struct fuse_fi
486527

487528
return -nsi_errno_from_mid(err);
488529
}
530+
#endif
489531

532+
#if defined(CONFIG_FUSE_LIBRARY_V3)
533+
static int fuse_fs_access_truncate(const char *path, off_t size, struct fuse_file_info *fi)
534+
{
535+
NSI_ARG_UNUSED(fi);
536+
#else
490537
static int fuse_fs_access_truncate(const char *path, off_t size)
491538
{
539+
#endif
492540
struct op_args_truncate args;
493541
int err;
494542

@@ -521,18 +569,35 @@ static int fuse_fs_access_statfs(const char *path, struct statvfs *buf)
521569
return 0;
522570
}
523571

572+
#if defined(CONFIG_FUSE_LIBRARY_V3)
573+
static int fuse_fs_access_utimens(const char *path, const struct timespec tv[2],
574+
struct fuse_file_info *fi)
575+
{
576+
NSI_ARG_UNUSED(fi);
577+
#else
524578
static int fuse_fs_access_utimens(const char *path, const struct timespec tv[2])
525579
{
580+
#endif
526581
/* dummy */
527582
NSI_ARG_UNUSED(path);
528583
NSI_ARG_UNUSED(tv);
529584
return 0;
530585
}
531586

587+
#if defined(CONFIG_FUSE_LIBRARY_V3)
588+
static void *fuse_fs_access_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
589+
{
590+
NSI_ARG_UNUSED(conn);
591+
NSI_ARG_UNUSED(cfg);
592+
593+
sem_post(&fuse_started);
594+
return NULL;
595+
}
596+
#endif
597+
532598
static struct fuse_operations fuse_fs_access_oper = {
533599
.getattr = fuse_fs_access_getattr,
534600
.readlink = NULL,
535-
.getdir = NULL,
536601
.mknod = NULL,
537602
.mkdir = fuse_fs_access_mkdir,
538603
.unlink = fuse_fs_access_unlink,
@@ -543,7 +608,6 @@ static struct fuse_operations fuse_fs_access_oper = {
543608
.chmod = NULL,
544609
.chown = NULL,
545610
.truncate = fuse_fs_access_truncate,
546-
.utime = NULL,
547611
.open = fuse_fs_access_open,
548612
.read = fuse_fs_access_read,
549613
.write = fuse_fs_access_write,
@@ -559,19 +623,24 @@ static struct fuse_operations fuse_fs_access_oper = {
559623
.readdir = fuse_fs_access_readdir,
560624
.releasedir = NULL,
561625
.fsyncdir = NULL,
562-
.init = NULL,
626+
#if defined(CONFIG_FUSE_LIBRARY_V3)
627+
.init = fuse_fs_access_init,
628+
#endif
563629
.destroy = NULL,
564630
.access = NULL,
565631
.create = fuse_fs_access_create,
632+
#if !defined(CONFIG_FUSE_LIBRARY_V3)
566633
.ftruncate = fuse_fs_access_ftruncate,
567-
.fgetattr = NULL,
634+
#endif
568635
.lock = NULL,
569636
.utimens = fuse_fs_access_utimens,
570637
.bmap = NULL,
638+
#if !defined(CONFIG_FUSE_LIBRARY_V3)
571639
.flag_nullpath_ok = 0,
572640
.flag_nopath = 0,
573641
.flag_utime_omit_ok = 0,
574642
.flag_reserved = 0,
643+
#endif
575644
.ioctl = NULL,
576645
.poll = NULL,
577646
.write_buf = NULL,
@@ -615,15 +684,35 @@ void ffsa_init_bottom(const char *fuse_mountpoint, struct ffa_op_callbacks *op_c
615684
nsi_print_error_and_exit("%s is not a directory\n", fuse_mountpoint);
616685
}
617686

687+
#if defined(CONFIG_FUSE_LIBRARY_V3)
688+
/* Fuse3's fuse_daemonize() changes the cwd to "/" which is a quite undesirable
689+
* side-effect, so we will revert back to where we were once it has initialized
690+
*/
691+
char *cwd = getcwd(NULL, 0);
692+
693+
err = sem_init(&fuse_started, 0, 0);
694+
if (err) {
695+
nsi_print_error_and_exit("Failed to initialize semaphore\n");
696+
}
697+
#endif
698+
618699
err = sem_init(&op_queue.op_done, 0, 0);
619700
if (err) {
620701
nsi_print_error_and_exit("Failed to initialize semaphore\n");
621702
}
622703

623704
err = pthread_create(&fuse_thread, NULL, ffsa_main, (void *)fuse_mountpoint);
624705
if (err < 0) {
625-
nsi_print_error_and_exit("Failed to create thread for fuse_fs_access_main\n");
706+
nsi_print_error_and_exit("Failed to create thread for ffsa_main()\n");
707+
}
708+
709+
#if defined(CONFIG_FUSE_LIBRARY_V3)
710+
if (cwd != NULL) {
711+
sem_wait(&fuse_started);
712+
chdir(cwd);
713+
free(cwd);
626714
}
715+
#endif
627716
}
628717

629718
void ffsa_cleanup_bottom(const char *fuse_mountpoint)

0 commit comments

Comments
 (0)