example/passthrough_hp: Fix . and .. readdir lookup count
Commit 170edc6a8ef0 added dot and dotdot (. and ..) to readdir
results, but introduced an issue when max number of entries
was reached - lookup count must not be decreased without
doing the lookup.
With ext4 as underlying file system readir seems to return . and ..
at random offsets and randomly failed xfstests for me.
This also fixes indentation, as passthrough_hp.cc does not follow
the linux indentation style (if we decide to fix this, it needs
to be done for the entire file).
I see random ENOTCONN failures in xfstest generic/013 and generic/014
in my branch, but earliest on the 2nd run - takes ~12hours to get
the issue, but then there are no further information logged.
ENOTCONN points to a daemon crash - I need backtraces and a core dump.
This adds optional handling of fatal signals to print a core dump
and optional syslog logging with these new public functions:
fuse_set_fail_signal_handlers()
In addition to the existing fuse_set_signal_handlers(). This is not
enabled together with fuse_set_signal_handlers(), as it is change
in behavior and file systems might already have their own fatal
handlers.
fuse_log_enable_syslog
Print logs to syslog instead of stderr
fuse_log_close_syslog
Close syslog (for now just does closelog())
Code in fuse_signals.c is also updated, to be an array of signals,
and setting signal handlers is now down with a for-loop instead
of one hand coded set_one_signal_handler() per signal.
Bernd Schubert [Thu, 20 Jun 2024 12:32:54 +0000 (14:32 +0200)]
Add list of libfuse (kernel) operations
This is to document operations and to also list
their in/out arguments.
This list was auto generated and only partly verified,
use with care. Not all operations are supported by
libfuse yet.
gandalfs_cat [Sun, 23 Jun 2024 11:28:30 +0000 (04:28 -0700)]
high-level: add fmask and dmask options
dmask: umask applied to directories
fmask: umask applied to non-directories
to get "typical" permission bits for regular files (0644) and directories (0755), a single
umask option is not sufficient (or well, it isn't the way fuse implements it)
there is precident for separate umask and dmask options in other
filesystems (see for example fat: https://github.com/torvalds/linux/tree/master/fs/fat)
this addition should not affect backward-compatibility; the original
umask option retains the same meaning, but non-zero fmask or
dmask will override it.
Miklos Szeredi [Thu, 13 Jun 2024 11:57:25 +0000 (13:57 +0200)]
libfuse: null-terminate buffer in fuse_req_getgroups()
After reading the file /proc/$PID/task/$PID/status the buffer wasn't
terminated with a null character. This could theoretically lead to buffer
overrun by the subsequent strstr() call.
Since the contents of the proc file are guaranteed to contain the pattern
that strstr is looking for, this doesn't happen in normal situations.
yangyun [Tue, 4 Jun 2024 12:57:14 +0000 (20:57 +0800)]
fix useless fuse_init_intr_signal in high-level api
The code `fuse_init_intr_signal` in `_fuse_new_317` is useless
since commit 8ee553dac ("fuse_new(): don't accept options that
don't make sense for end-users") has remove the conf.intr option
for end-users. The conf.intr is always zero (i.e., disabled) here.
Move `fuse_init_intr_signal` after the user-defined `init()` function,
so that conf.intr and conf.intr_signal has been configured by the user.
Josef Bacik [Fri, 7 Jun 2024 18:49:10 +0000 (14:49 -0400)]
libfuse: have passthrough_hp return an error with invalid mount options
generic/003 fails currently because if you specify -o relatime we will
fail to mount, but not return an error, so the test thinks that we
support relatime and then hilarity ensues. Set ret so that if we get
any failures while trying to mount we will properly error out.
Bernd Schubert [Tue, 4 Jun 2024 11:56:09 +0000 (13:56 +0200)]
Make struct fuse_req::ctr a C11 _Atomic
The variable is not modified exclusively with locks since commit cef8c8b24902 ("Add support for no_interrupt") anymore.
That commit is safe, but might be error prone to future updates.
Changing it to a C11 _Atomic should avoid issues.
yangyun50 [Tue, 4 Jun 2024 11:50:48 +0000 (19:50 +0800)]
Add support for no_interrupt (#956)
The function fuse_session_process_buf_int() would do much things
for FUSE_INTERRUPT requests, even there are no FUSE_INTERRUPT requests:
1. check every non-FUSE_INTERRUPT request and add these requests to the
linked list(se->list) under a big lock(se->lock).
2. the function fuse_free_req() frees every request and remove them from
the linked list(se->list) under a bing lock(se->lock).
These operations are not meaningful when there are no FUSE_INTERRUPT requests,
and have a great impact on the performance of fuse filesystem because the big
lock for each request.
In some cases, FUSE_INTERRUPT requests are infrequent, even none at all.
Besides, the user-defined filesystem may do nothing for FUSE_INTERRUPT requests.
And the kernel side has the option "no_interrupt" in struct fuse_conn. This kernel option
can be enabled by return ENOSYS in libfuse for the reply of FUSE_INTERRUPT request.
But I don't find the code to enable the "no_interrupt" kernel option in libfuse.
So add the no_interrupt support, and when this operaion is enabled:
1. remove the useless locking operaions and list operations.
2. return ENOSYS for the reply of FUSE_INTERRUPT request to inform the kernel to disable
FUSE_INTERRUPT request.
Bernd Schubert [Mon, 27 May 2024 13:24:10 +0000 (15:24 +0200)]
Remove most includes in compat.c (#954)
compat.c is supposed to be standalone to provide compat ABI symbols.
Including fuse header files can cause conflicts - just the opposite
of what compat.c was made for.
Bernd Schubert [Mon, 27 May 2024 08:18:19 +0000 (10:18 +0200)]
Add a .clang-format file (#952)
This is direct copy of <linux>/.clang-format as
this project was initiated with linux style. Some
lines that were auto-generated are removed
("# Taken from:...).
Some files like example/passthrough_hp.cc use
a different style - these files probably should
be cleaned up when major changes are done to them.
Amir Goldstein [Mon, 13 May 2024 13:30:25 +0000 (16:30 +0300)]
Enable passthrough mode for read/write operations (#919)
Add support for filesystem passthrough read/write of files.
When the FUSE_PASSTHROUGH capability is enabled, the FUSE server may
decide, while handling the "open" or "create" requests, if the given
file can be accessed by that process in "passthrough" mode, meaning that
all the further read and write operations would be forwarded by the
kernel directly to the backing file rather than to the FUSE server.
All requests other than read or write are still handled by the server.
This allows for an improved performance on reads and writes, especially
in the case of reads at random offsets, for which no (readahead)
caching mechanism would help, reducing the performance gap between FUSE
and native filesystem access.
Extend also the passthrough_hp example with the new passthrough feature.
This example opens a kernel backing file per FUSE inode on the first
FUSE file open of that inode and closes the backing file on the release
of the last FUSE file on that inode.
All opens of the same inode passthrough to the same backing file.
A combination of fi->direct_io and fi->passthrough is allowed.
It means that read/write operations go directly to the server, but mmap
is done on the backing file.
This allows to open some fds of the inode in passthrough mode and some
fd of the same inode in direct_io/passthrough_mmap mode.
Signed-off-by: Alessio Balsini <balsini@android.com> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Bernd Schubert [Mon, 13 May 2024 10:32:06 +0000 (12:32 +0200)]
Add in the libfuse version a program was compiled with (#942)
The API stays the same, the libfuse version comes from
inlined functions, which are defined fuse_lowlevel.h
and fuse.h. As these inlined functions are defined in the header
files they get added into the application, similar as if these
were preprocessor macros.
Macro vs inlined function is then just a style issue - I personally
prefer the latter.
fuse_session_new() -> static inlinei, in the application
_fuse_session_new -> inside of libfuse
fuse_new() -> static inline, in the application
_fuse_new() -> inside of libfuse
Note: Entirely untested is the fuse 30 api - we need a test
for it. And we do not have any ABI tests at all.
Josef Bacik [Fri, 10 May 2024 15:52:20 +0000 (11:52 -0400)]
Handle NO_OPEN/NO_OPENDIR support automatically (#949)
If the file system doesn't provide a ->open or an ->opendir, and the
kernel supports FUSE_CAP_NO_OPEN_SUPPORT or FUSE_CAP_NO_OPENDIR_SUPPORT,
allow the implementation to set FUSE_CAP_NO_OPEN*_SUPPORT on conn->want
in order to automatically get this behavior. Expand the documentation
to be more explicit about the behavior of libfuse in the different cases
WRT this capability.
We already have some C11 pieces like Static_assert and we are likely
going to add more - tell meson to use C11.
Plain C11 does not work as there are several language extension,
like typeof - part of C23 only. We might be able to fix/workaround
such extensions with compiler ifdef, but then I prefer gnu11 over
checking which compiler is used (example gcc has __typeof vs
clangs __typeof++). And compiler extension would also defeat pedantic.
[libFuse 3.16.2]Compilation failure on freeBSD #936 (#938)
Despite the creation of the header file fuse_config.h during LibFUSE
version 3.16.2's Meson build process, the BSD mount_bsd.c file continues to reference config.h. Consequently, this discrepancy results in compilation failures.
Use single place to define the version and increase version to 3.17.0 (#932)
* Use single place to define the version
Defining the version in fuse_common.h, is removed, it is defined
through meson and provided by "libfuse_config.h". I.e. it avoids
to define the version twice - once in meson and once in
fuse_common.h.
Ideal would be to set integers in the meson file and create the version
string from these integers. However, meson requires that "project"
is the first meson.build keyword - with that it requires to
set the version from a string and then major/minor/hotfix integers
are created from string split.
Signed-off-by: Bernd Schubert <bernd.schubert@fastmail.fm>
* Increase the version to 3.17.0
This is to prepare the branch for the next release.
passthrough_ll: fix fd leaks in lo_destroy() (#929)
By virtio-fs and libfuse fuse_custom_io, passthrough_ll could be
a virtio filesystem device backend, this bug was found when doing
mount, fsstress and umount repeatedly.
Signed-off-by: Xiaoguang Wang <lege.wang@jaguarmicro.com> Co-authored-by: Xiaoguang Wang <lege.wang@jaguarmicro.com>
If user updates conn->max_write in fuse_lowlevel_ops' init() method, do_init()
will miss the "conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE" judgment,
and ->init method will be called after it, which obviously is a bug.
Signed-off-by: Xiaoguang Wang <lege.wang@jaguarmicro.com> Co-authored-by: Xiaoguang Wang <lege.wang@jaguarmicro.com>
Add more documentation for FUSE_CAP_EXPORT_SUPPORT (#917)
Add more documentation for FUSE_CAP_EXPORT_SUPPORT
Also remove the flag from passthrough_ll.c and passthrough_hp.cc
as these implementations do _not_ handle that flag. They just
cast fuse_ino_t to an inode and cause a heap buffer overflow
for unknown objects (simplest reproducer are the examples
in "man 2 open_by_handle_at", but to unmount/mount the file
system after name_to_handle_at and before open_by_handle_at).
farlongsignal [Sun, 24 Mar 2024 20:54:19 +0000 (21:54 +0100)]
fix readdirplus when filler is called with zero offset (#896)
fixes #235
In fill_dir_plus(), there's a lookup for caching dirent attributes.
However, when offset = 0 the cache metadata from the lookup is lost
as only the entry attributes are passed when added to the list. Kernel
doesn't cache the attributes since .ino = 0.
This change moves the entry lookup to happen just before the relevant
fuse_add_direntry_plus() calls
legezywzh [Thu, 21 Mar 2024 09:02:05 +0000 (17:02 +0800)]
reset got_init after handling FUSE_DESTROY message (#910)
User may still need to mount same fuse filesystem after umounting
it(In this case, the userspace filesystem server needs to keep live),
and after handling FUSE_DESTROY message, new FUSE_INIT message may come,
so need to reset got_init to be zero.
Signed-off-by: Xiaoguang Wang <lege.wang@jaguarmicro.com>
FredyVia [Wed, 20 Mar 2024 15:08:04 +0000 (23:08 +0800)]
Add FUSE_FILL_DIR_DEFAULTS enum (#903)
In order to use the fuse_fill_dir_t function in a C++ program, add the enum item:
FUSE_FILL_DIR_DEFAULTS
Without this change g++ compilation failed with
example/hello.c:94:35: error: invalid conversion from ‘int’ to ‘fuse_fill_dir_flags’ [-fpermissive]
94 | filler(buf, ".", NULL, 0, 0);
| ^
| |
| int
Bernd Schubert [Wed, 20 Mar 2024 14:25:41 +0000 (15:25 +0100)]
Fix example/fix-notify_inval_inode.c (#908)
Similar issue as fixed in commit 3c7ba570 "examples/notify_store_retrieve: Add a clean shutdown".
Basically a clean shutdown was missing, but even with clean
shutdown it does not work, as kernel side releases inodes before
sending FUSE_DESTROY - the intervaled thread then gets
-ENOENT.
Bernd Schubert [Wed, 20 Mar 2024 11:59:15 +0000 (12:59 +0100)]
Add final "meson setup --reconfigure" to README.md
This reconfigure is recommended to ensure the build system
(ninja/cmake/...) get the updated meson config. They
typically do, but it depends on file time stamps - is
a potential random error source.
Bernd Schubert [Tue, 19 Mar 2024 23:32:40 +0000 (00:32 +0100)]
Build clang/sanitized build first
This was stalling - easier to check what happens
when it fails fast. And in general, sanitized
builds are faster than valgrind and detect almost
as much errors as valgrind (same level would be
achieved with MSAN, but that is hard to use),
so failures can be detected faster whan sanitizers
run first.
Bernd Schubert [Tue, 19 Mar 2024 23:07:44 +0000 (00:07 +0100)]
Fix use-after-free in example/poll.c
As noticed by valgrind in issue #907 example/poll.c
triggers a use-after-free
==85200== Thread 2:
==85200== Invalid read of size 4
==85200== at 0x485E54A: send_notify_iov (fuse_lowlevel.c:2267)
==85200== by 0x485E54A: fuse_lowlevel_notify_poll (fuse_lowlevel.c:2289)
==85200== by 0x1096F2: fsel_producer (poll.c:245)
==85200== by 0x4897EA6: start_thread (pthread_create.c:477)
==85200== by 0x49ADA6E: clone (clone.S:95)
==85200== Address 0x5291d68 is 392 bytes inside a block of size 920 free'd
==85200== at 0x48399AB: free (vg_replace_malloc.c:538)
==85200== by 0x485A12C: fuse_destroy (fuse.c:5103)
==85200== by 0x486220F: fuse_main_real (helper.c:389)
==85200== by 0x1091D6: main (poll.c:288)
==85200== Block was alloc'd at
==85200== at 0x483AB65: calloc (vg_replace_malloc.c:760)
==85200== by 0x485BAA0: fuse_session_new (fuse_lowlevel.c:3036)
==85200== by 0x4859AF2: fuse_new@@FUSE_3.1 (fuse.c:4966)
==85200== by 0x4862129: fuse_main_real (helper.c:345)
==85200== by 0x1091D6: main (poll.c:288)
Issue is that the "fsel_producer" thread is still active after
fuse_destroy - it gets destructed too late.
Bernd Schubert [Wed, 20 Mar 2024 00:14:07 +0000 (01:14 +0100)]
Fix test failures: Create missing mount dir
Tests were failing because mount dir was missing.
Unclear to me why this became only recently an issue
(github internal - out of the sudden tests were hanging).
Bernd Schubert [Wed, 20 Mar 2024 00:01:49 +0000 (01:01 +0100)]
ci-build.sh: Reduce pytest --maxfail from 99 to 1
We want to see errors - reduce allowed errors.
With --maxfail=99 tests out of the sudden started to hang
in github, without a change in libfuse (I had actually tested
to previous release tags). With --maxfail=1 pytest aborts
and we see failing github.
Also increase python log level to NOTSET - NOTSET should print
all messages.
Bernd Schubert [Tue, 5 Mar 2024 23:37:53 +0000 (00:37 +0100)]
ci-build.sh: Always install and add s-bit for fusermount3
As per pull #898, fusermount3 had a severe issue that
should have been detected by ASAN. I guess tests used
the system default and not the sanitized binary.
Order of execution of fusermount3 is to try
1) full install path
if that fails
2) just fusermount3
So tests should be fixed by installing libfuse, setting the s-bit
on fusermount3 and then to run the tests.
Bernd Schubert [Tue, 5 Mar 2024 14:47:50 +0000 (15:47 +0100)]
posix_spawn style updates
- This adds a wrapper function for the call sequence
of posix_spawn and posix_spawnp.
- Replaces perror() with fuse_log - the latter
can be redirected through the file system log function
and gives better end user friendly output
- other minor changes, like variable renames
- no functional change
Client code might allocate a lot of memory before starting the mount.
Fork is slow for processes that are using a lot of memory. But
posix_spawn fixes that.
Another issue with fork is if the process is also doing RDMA - this
might lead to data corruption, as least if memory used for RDMA
is not marked with MADV_DONTFORK. At least with linux kernels
before 5.12.
Also see https://blog.nelhage.com/post/a-cursed-bug/ for more details
Change by Bernd:
This also prepares the new fusermount option "--comm-fd", but keeps
the previous way to pass the parameter as env variable. In a future
release (exact data to be determined) we are going to remove usage
of the env variable and will switch to the new parameter.
Bernd Schubert [Tue, 5 Mar 2024 17:09:33 +0000 (18:09 +0100)]
fusermount: Fix head-buffer-overflow in extract_x_options
Commit 74b1df2e introduced a heap-buffer-overflow, as
allocated memory was not initialized and extract_x_options
was also not checking for the remaining buffer size.
Fix is to initialize the buffer and to also not exceed the buffer
size. Actually not exceeding buffer size is rather complex with C
and introduced quite some code changes.
Also fixed is a memory leak of allocated buffers in the commit
mentioned above.
Bernd Schubert [Wed, 10 Jan 2024 14:11:34 +0000 (15:11 +0100)]
example/notify_store_retrieve: Fix races and handle errors
This test was racy, the lookup counter must only be increased once
kernel side has lookup completed and knows about the inode.
However, this is still racy as
So actually on libfuse side even after returning from kernel side
it is not ensured that the kernel has created the inode. I.e.
using lookup_cnt in the test is still racy.
A new variabled 'open_cnt' is added that is only increased in open
Using open_cnt should be safe to use as kernel side (with atomic-open)
first does lookup, from that data creates the inode and only then sends
an open request. I.e. update_fs_loop() must only call
fuse_lowlevel_notify_store() once it is absolutely sure kernel side has
created the inode (open_cnt) and when it is sure the kernel inode still
exists (lookup_cnt).
Not really nice, but we actually need to accept some errors, as
these still come up at umount time. Typically it is hard to hit,
but tests in github actually frequently get it. Actually, it can be
easily reproduced by commenting out the sleep line in
update_fs_loop(). Underlying issue is that kernel side is
sending ->destroy() only when it already internally released all
inodes - too late for this test. The errors I run into are ENOENT
and EBADFD, but I added back in ENODEV for safety.
In order to avoid any other kind races mutex lock is also introduced.
Bernd Schubert [Mon, 26 Feb 2024 18:09:00 +0000 (19:09 +0100)]
Fix tests/test_write_cache in write back mode (#892)
This test could fail whenever a something (kernel, userspace) decides
to flush in between of two 2048B writes. These two writes are supposed
to be merged into a single 4906 byte write by the kernel writeback cache,
but _sometimes_ the test fails because 2048 byte writes get through.
Fixes #882
Solution here is a modification how the test works - instead
of requiring an exact aggregation of 2x2048B into 4096B,
it now writes 64x2048B and requires in write-back modes
the number of received writes requests is lower than 64 - we
can expect that at least some writes get aggregated, but we do
know how many.
yangyun [Fri, 23 Feb 2024 06:16:05 +0000 (14:16 +0800)]
Enable direct IO for passthrough examples when open has flag O_DIRECT
Shared locks (parallel_direct_writes) cannot be enabled for O_DIRECT, as
O_DIRECT may be set past file open time with fcntl(fd, F_SETFD, ...).
Kernel side fuse has precautions for shared lock direct-IO (direct_io in
libfuse), as it needs an exclusive inode lock when direct and page cache
IO happend at the same time.
In order to enjoy the parallel_direct_writes feature (i.e., get a shared
lock, not exclusive lock) for writes to the same file), direct_io is needed.
The feature direct_io is corresponding to FOPEN_DIRECT_IO in fuse kernel.
FOPEN_DIRECT_IO and O_DIRECT are not entirely the same as described above.
So enable direct_io (i.e., FOPEN_DIRECT_IO in fuse kernel) to enjoy parallel
direct_writes.
Some patches related to FOPEN_DIRECT_IO and O_DIRECT are below:
Matthew [Sat, 24 Feb 2024 06:56:49 +0000 (22:56 -0800)]
Passthrough options starting with "x-" to mtab (#894)
This implements #651, tested with bindfs.
"x-*" options are comments meant to be interpreted by userspace.
#651 is about some 3rd party mount options like 'x-gvfs-notrash'.
This also removes the test if /etc/mtab is a symlink.
This test was added in commit 5f28cd15ab43c741f6d116be4d3a9aa5d82ab385
and the corresponding ChangeLog entry in this commit points to mount
issues for read-only mtab.
However, in all recent Linux distributions /etc/mtab is a symlink to
/proc/self/mounts and never writable. In fact, util-linux 2.39
(libmount) entirely removed support for a writable mtab.
At least since util-linux 2.19 (10-Feb-2011) /run/mount/utab is used
as replacement for userspace mount entries..
yangyun [Fri, 23 Feb 2024 03:06:08 +0000 (11:06 +0800)]
passthrough_example: make parallel_direct_writes more clearly
Move the parallel_direct_writes enable action to the init function in high level API,
it is more recommended just like commit 8ee553dac. Besides, add some comments to show
that the feature parallel_direct_writes is depend on the feature direct_io (refer to link: https://lwn.net/ml/linux-fsdevel/ 20230918150313.3845114-1-bschubert@ddn.com for the reason).
bigbrotherwei [Wed, 17 Jan 2024 15:58:27 +0000 (23:58 +0800)]
Add processing for FUSE_CAP_HANDLE_KILLPRIV and disable it by default
'FUSE_CAP_HANDLE_KILLPRIV' is not enabled by default anymore, as that
would be a sudden security issue introduced by a new ABI and API
compatible libfuse version.
Bernd Schubert [Mon, 4 Dec 2023 14:58:45 +0000 (15:58 +0100)]
Add FUSE_CAP_DIRECT_IO_ALLOW_MMAP and use in passthrough_hp
This is not called FUSE_CAP_DIRECT_IO_RELAX, as the kernel flag
FUSE_DIRECT_IO_RELAX is supposed to be renamed to
FUSE_DIRECT_IO_ALLOW_MMAP. The corresponding kernel patches just
did not land yet.
Bernd Schubert [Tue, 26 Dec 2023 10:53:55 +0000 (11:53 +0100)]
examples/notify_store_retrieve: Add a clean shutdown
On shutdown update_fs_loop() was failing frequently in github
test with ENOENT, but only ENODEV was tested for and only for the.
With clean shutdown there is no need to test for such errors at all.
George Hilliard [Sun, 19 Nov 2023 10:27:45 +0000 (04:27 -0600)]
Clarify fuse_lowlevel poll() docstring (#862)
The original docstring was confusing; it was not clear that the ph must
be retained indefinitely, nor was it clear that the client *also* needs
to reply to the poll call immediately.
Clarify this by explaining that it is only necessary to retain a single
handle, that the client must retain ph, and that it must immediately
call reply.
fdinoff [Thu, 16 Nov 2023 11:23:20 +0000 (06:23 -0500)]
Pass FUSE_PARALLEL_DIROPS to kernel (#861)
This tells the kernel that parallel lookup/readdir operations are
supported. This is enabled by default but was not passed to the kernel
so you always get the synchronized version.