aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fuse_lowlevel.c
AgeCommit message (Collapse)AuthorLines
2025-09-22FUSE_INIT handler: Set got_init only shortly before send_reply_okBernd Schubert-1/+7
A previous commit added single thread behavior as long as se->got_init is not set, especially as buffer allocation should be done after got_init only. Technically it should not make a difference in current libfuse design, as more worker threads are only allocated after the FUSE_INIT handler is completely done. That might at some point change, though. In general it is cleaner to set se->got_init, when the init handler is done. Done as separate commit, as this introduces a slight risk to break something - backport to older version should be done carefully. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-09-19io-uring: re-initialize fields in struct fuse_reqBernd Schubert-12/+11
In io-uring mode these requests are always re-used and not allocated - we need to re-initialize them. In order to set flags to zero a struct holding the flags had to be added. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-09-19fuse_log: Add __attribute__((format(printf, ) and fix warningsBernd Schubert-8/+15
fuse_log() did not have that attribute and so compilers didn't give warnings for plain printf(). Add the attribute and fix related warnings. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-09-19fuse_lowlevel.c: allow passing ops as NULLAlik Aslanyan-1/+25
During testing of LACT using various sanitizers issue with libfuse.so leaking memory and reading uninitialized memory was uncovered. While this was due to ABI misusage on the side of fuser (Rust wrapper for libfuse.so), we now allow creating a no-op session by passing ops as NULL. fuser and other libfuse users is using fuse_session_new() with NULL struct fuse_lowlevel_ops *op and op_size=0. This resulted in a warning, but otherwise succeeded. The resulting fuse_session is just passed to fuse_session_mount() so that libfuse could do the actual mount. Fuse kernel request handling is not done through libfuse but their own layer. Edit by Bernd: - Update the commit message - moved using null_ops to fuse_session_new_30() as that is actually called by the external fuse_session_new(). - forbidding NULL struct fuse_lowlevel_ops *op and 0 op_size in fuse_session_new_versioned() - various other NULL ptr checks in fuse_session_new() that now result in failure. Signed-off-by: Alik Aslanyan <inline0@pm.me> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-09-13libfuse: fix COPY_FILE_RANGE interfaceMiklos Szeredi-5/+61
The FUSE protocol uses struct fuse_write_out to convey the return value of copy_file_range, which is restricted to uint32_t. But the COPY_FILE_RANGE interface supports a 64-bit size copies. Currently the number of bytes copied is silently truncated to 32-bit, which is unfortunate at best. Implement the COPY_FILE_RANGE_64 interface which is identical to the old one, except the number of bytes copied is returned in a 64-bit value. The library interface remains the same. If the kernel does not support the new interface or the server is running as a 32-bit process, limit the copy size to size to UINT_MAX - 4096. Edit by Bernd: Keep ioctl_64bit and add use new bit is_copy_file_range_64 to keep flags separated from each other - easier code readability IMO. Reported-by: Florian Weimer <fweimer@redhat.com> Closes: https://lore.kernel.org/all/lhuh5ynl8z5.fsf@oldenburg.str.redhat.com/ Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-08-22Allow applications to retrieve the req payload (io-uring only)Bernd Schubert-0/+12
With io-uring the req owns the payload buffer, the application can directly access it and copy data into it. fuse_buf_copy_one() already has a check for dstmem == srcmem and skips data copies. fuse_reply_data fuse_reply_data_uring fuse_buf_copy fuse_buf_copy_one Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-07-22Split fuse-io-uring startupBernd Schubert-5/+9
Start the ring threads before sending fuse_reply_ok() so that io-uring startup issues can be non-fatal. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-07-16Avoid double unmount on FUSE_DESTROYBernd Schubert-11/+22
This is a long standing issue, a system could have unmounted /path/to/mnt and then fuse-client/kernel would send FUSE_DESTROY, which would then again try a umount. Given that FUSE_DESTROY is async, that umount might arrive any time later and might possibly unmount a wrong mount point. A warning as in issue #1286 is just minor to that. Code wise this uses atomics to free the char *, as FUSE_DESTROY might race with a signal and a double free might be possible without proctection. A lock might run into the same issue, if the signal would arrive at the wrong time a double lock would be possible. Additionally, fuse_session_mount() is updated, to first duplicatate the pointer and to then do the kernel mount - reverting the kernel mount in case of strdup() failure is much harder. Closes: https://github.com/libfuse/libfuse/issues/1286 Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-07-16Add statx supportJoanne Koong-1/+65
This commit adds libfuse support for FUSE_STATX requests on linux distributions. Currently, statx is only supported on linux. To make the interface a ergonomic as possible (eg using native 'struct statx' vs 'struct fuse_statx'), this implementation gates the 'struct statx' changes by #ifdef linux. Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
2025-06-27license: s/COPYING/GPL2.txt, s/COPYING.LIB/LGPL2.txtizxl007-1/+1
Signed-off-by: izxl007 <zeng.zheng@zte.com.cn>
2025-06-25Catch up with fuse_send_data_iov() signature changes in the fallback caseGleb Popov-2/+3
Signed-off-by: Gleb Popov <6yearold@gmail.com>
2025-06-22Clarify offset field is signed despite uint64_t typeizxl007-0/+4
Add comment noting that the uint64_t offset in fuse_lseek_in is derived from kernel loff_t and should be treated as signed for negative offsets. Signed-off-by: izxl007 <zeng.zheng@zte.com.cn>
2025-06-18fuse: add support to FUSE_NOTIFY_INC_EPOCHLuis Henriques-0/+13
This patch adds support for the FUSE INC_EPOCH notify. This new operation simply increments the FUSE connection epoch value, allowing to invalidate all the dentries next time they are revalidated. Signed-off-by: Luis Henriques <luis@igalia.com>
2025-05-28fuse_lowlevel.c: Remove duplicate descriptions of auto_unmountizxl007-1/+0
Signed-off-by: izxl007 <zeng.zheng@zte.com.cn>
2025-05-20conn->want conversion: Fix fuse_apply_conn_info_opts()Bernd Schubert-6/+72
fuse_apply_conn_info_opts() was applying to 'want_ext', which would cause conflicts with 'want' if the application applied its own flags to 'conn->want'. Solution is: - to move fuse_{set,unset,get}_feature_flag and convert_to_conn_want_ext() to fuse_lowlevel.c and to define them as part of the public API, although convert_to_conn_want_ext() should not be used - it is currently needed to be a public function due as it needs to be defined for the tests. Related to https://github.com/libfuse/libfuse/issues/1171 and https://github.com/libfuse/libfuse/pull/1172. Closes: https://github.com/libfuse/libfuse/issues/1171 Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-05-20Make conn->want/want_ext conversion non fatalBernd Schubert-8/+1
there are too many issues with conn->want and conn->want_ext conversion, for now just log a warning, but setting both flags is now not fatal anymore. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-30Support request timeoutsJoanne Koong-0/+5
This adds the libfuse changes needed to support request timeouts. A timeout may be set by the server in its init call. If a request is not completed by the timeout, the connection will be aborted by the kernel. Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
2025-04-29fuse_lowlevel.c: Fix a small spelling mistakeizxl007-1/+1
Signed-off-by: izxl007 <zeng.zheng@zte.com.cn>
2025-04-28Set FUSE_CAP_OVER_IO_URING flag - allow io-uring modeBernd Schubert-0/+3
So far it was disabled as the series was not complete yet. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28env variables to override default io-uring enable and q-depthBernd Schubert-2/+11
We want to especially test with and without io-uring being enabled. Ideally without modifying all tests - that is what the env variable can be used for. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28Add fuse_req_is_uring() to check if a req comes through io-uringBernd Schubert-0/+5
This might be useful to optimize code paths. For example, with io-uring the request buffer is valid until the request is replied to, while without io-uring the request buffer is only valid in current thread context. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28fuse: Add io-uring optionsBernd Schubert-1/+9
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28Add fuse-io-uring reply supportBernd Schubert-27/+43
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28Add fuse_session_process_uring_cqeBernd Schubert-22/+111
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28fuse_ll_ops: Make fuse_ino_t constBernd Schubert-1/+1
It will never be modified, should be const. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28fuse_lowlevel: Split fuse_send_msgBernd Schubert-19/+32
The actual function to write to /dev/fuse is offloaded into _fuse_send_msg() Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28Add support for ring creation in fuse_lowlevel.cBernd Schubert-2/+29
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28Add container_of and ROUND_UP macrosBernd Schubert-4/+0
Needed by follow up commits. container_of is actually just moved/consolidated to util.h. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-28fuse_lowlevel: Add support for header/payload separationBernd Schubert-169/+597
Header/payload separation is part of the fuse-io-uring protocol and might be later on for /dev/fuse legacy communication as well. This is a preparation commit, for now fuse_ll_ops2 is unused. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-24Fix multi-threaded fuse session exitBernd Schubert-3/+15
Issue with previous code was that fuse_session_exit() didn't wake up the semaphore in fuse_loop_mt.c. Lock, semaphore and all uses of checking for "exited" are now moved to struct fuse_session to have it available for the signal handler. This also removes internal fuse_session_reset() calls, as that makes testing hard. From git history I also don't see why it was added. Closes: https://github.com/libfuse/libfuse/issues/997 Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-07fuse_lowlevel: Set bufsize if HAVE_SPLICE is not define and avoid raceBernd Schubert-6/+10
These are several buf size fixes 1) Set bufsize when HAVE_SPLICE is not defined. Addresses https://github.com/libfuse/libfuse/issues/1184 2) Check in the read retry condition for bufsize, i.e. the value passed to read and not for the buf->mem_size. Using buf->mem_size can be startup racy. Additionally we now also set bufsize on allocation to avoid these races. 3) Allocation and value assigned needs to follow the pattern bufsize = se->bufsize; buf_alloc(bufsize, internal) buf->mem_size = bufsize; I.e. bufsize has to be retrieved first, as se->bufsize might change at anytime - the value used for allocation and must not differ from the value actually used. This also tries to set large sizes in passthrough_hp, to catch issues in xfstests - though requires to set /proc/sys/fs/fuse/max_pages_limit Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-04-04meson: add option for enabling usdtJoanne Koong-1/+26
Default is having usdt disabled. Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
2025-04-02fuse_lowlevel: add tracepoints for request receiving, processing, and replyingJoanne Koong-0/+23
Add user statically-defined tracepoints for request lifecycle. Verified by: [machine]$ readelf -n /home/libfuse/build/lib/libfuse3.so | grep -A 1000 '.note.stapsdt' Displaying notes found in: .note.stapsdt Owner Data size Description stapsdt 0x00000035 NT_STAPSDT (SystemTap probe descriptors) Provider: libfuse Name: request_receive Location: 0x0000000000016360, Base: 0x00000000000002fc, Semaphore: 0x0000000000000000 Arguments: -4@%edi stapsdt 0x00000055 NT_STAPSDT (SystemTap probe descriptors) Provider: libfuse Name: request_reply Location: 0x0000000000017c0f, Base: 0x00000000000002fc, Semaphore: 0x0000000000000000 Arguments: 8@8(%r12) 4@(%r12) -4@4(%r12) -4@%r13d stapsdt 0x0000003e NT_STAPSDT (SystemTap probe descriptors) Provider: libfuse Name: request_process Location: 0x000000000001acf7, Base: 0x00000000000002fc, Semaphore: 0x0000000000000000 Arguments: 4@%r8d 4@%edx Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
2025-03-24fuse: Fix want flag conversionBernd Schubert-23/+7
32-bit conn->want flags been left to be ABI compatible to 3.10, even though the so version was changed. The more recent way is to use fuse_set_feature_flag(), which will use conn->want_ext. Given that we now have two flags (want and want_ext), we need to convert and that brought several issues - If the application sets conn->want, that needs to be set into the lower 32 bit of conn->want_ext. As the application might actually unset values, it really has to be a copy and not just 'or' - fixed now. - convert_to_conn_want_ext() actually needs to check for _modified_ conn->want and conn->want_ext - convert_to_conn_want_ext() must consider being called from high and lowlevel interfact, with different want_ext_default and want_default values. It is only a failure, if the application changed both, conn->want and conn->want_ext. This function was failing in issue #1171, because high level fuse_fs_init() was changing values and then lowlevel do_init() was incorrectly failing on that. This also adds a new test (test_want_conversion) and sets values into example/{hello.c,hello_ll.c} Also some more internal users of conn->want are converted to fuse_{set,unset}_feature_flag(). Closes: https://github.com/libfuse/libfuse/issues/1171 Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-03-14fuse_lowlevel: Simplify se->buf_reallocableBernd Schubert-11/+12
se->buf_reallocable is true when reading /dev/fuse is handled from internal functions - we can set the variable in fuse_session_receive_buf_internal(). With that we also don't need to have it an _Atomic variable anymore. In _fuse_session_receive_buf() we can use "bool internal" to check if the buffer can be re-allocated. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-03-14fuse_session_receive_buf: Fix the pipe buf sizeBernd Schubert-1/+11
This fixes dynamic buffer allocation in commit 0e0f43b79b9b ("Reallocate fuse_session buffer...") I noticed that when I increased the default fuse buf size as possible in recent kernels. Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-02-18Avoid nested function declarations in helper functionsBernd Schubert-4/+0
libfuse-3.17 introduced several functions that should only be called via inlined helper functions, never directly. To enforce this, these functions were declared within the inlined functions. However, this triggers the compiler warning "-Werror=nested-externs". While this warning is valid, the nested declarations were intentional to prevent direct usage of these functions. Rather than suppressing the warning with pragmas, move these function declarations outside the helper functions while maintaining the intended access restrictions through other means. Closes: https://github.com/libfuse/libfuse/issues/1134 Signed-off-by: Bernd Schubert <bschubert@ddn.com>
2025-02-09Rename to fuse_session_new_versionedBernd Schubert-16/+12
Similar previous renames to fuse_main_real_versioned, but here for the low level fuse_session_new. Also remove symbol versioned as part of "fuse_session_new" as that function is not part of the official API/ABI and to allow easier access with dlopen/dlsym. Also switch back to a macro fuse_session_new, just in case some code has some expectations on that. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2025-01-31fuse_lowlevel.c: drop incorrect comment from convert_to_conn_want_ext()Luis Henriques-2/+0
The comment is probably a leftover from older versions, as the application of the 32 bits of conn.capable_ext to conn.capable is done before function convert_to_conn_want_ext() is invoked. Signed-off-by: Luis Henriques <luis@igalia.com>
2025-01-31fuse_lowlevel.c: fix possible 64 bits value truncationLuis Henriques-1/+1
Because conn.want_ext is a uint64_t, copying it into a uint32_t may result in truncating it's value. This patch fixes a bug in do_init() where the 32 bits copy is again converted into a 64 bits value, because it will be used in convert_to_conn_want_ext(). Signed-off-by: Luis Henriques <luis@igalia.com>
2025-01-06Avoid global declarion of internal functions that are new in 3.17Bernd Schubert-4/+9
_fuse_new() is not supposed to be called by external users outside of internal functions or static inlined functions. This also removes several functions from lib/fuse_versionscript which where added and exported by commit 58f85bfa9b7d ("Add in the libfuse version a program...) as these are libfuse internal only. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2024-12-30Add 64-bit conn::{capable,want}_ext fieldsBernd Schubert-64/+108
The previous fields are left for ABI compatibility, although it is not beautiful to add that complexity when we have to increase the so-version as we had ABI breakage anyway. example/printcap is simplified to use an array, as every line would have needed to be modified anyway. Missing 'FUSE_CAP_PASSTHROUGH' was added. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2024-12-30fuse_lowlevel.c: define FUSE_MAXOP as CUSE_INITBernd Schubert-1/+6
We don't want FUSE_MAXOP calculated at compilation time, as the ABI limit is CUSE_INIT - better use that value directly. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
2024-12-18Rename _int to _internalBernd Schubert-4/+6
_int can be confused with 'integer'
2024-12-18Allow to have page aligned writesBernd Schubert-34/+92
Read/writes IOs should be page aligned as fuse server might need to copy data to another buffer otherwise in order to fulfill network or device storage requirements. Simple reproducer is example/passthrough* and opening a file with O_DIRECT - without this change writing to that file failed with -EINVAL if the underlying file system was using ext4 (for passthrough_hp the 'passthrough' feature has to be disabled). The mis-alignment from fuse kernel is not ideal, but we can handle it by allocation one page more than needed and then using a buffer that is set up to compensate for kernel misalignment. This also only set se->buf_reallocable to true when called by a libfuse internal caller - we do not know what external callers are doing with the buffer - update to commit 0e0f43b79b9b
2024-11-27support FUSE_TMPFILE in the low level APIHorst Birthelmer-0/+19
Note that name hashes and using paths as parameters makes it very hard to support anonymous files in the high level API. Known Issues: - tests have to bail out when O_TMPFILE is not supported. This will always be the case with high level passthrough implementations. - test_create_and_link_tmpfile has to be skipped due to unidentified problems with github runner
2024-11-21Fix alignment of allocation in fuse_reply_createVladimir Serbinenko-1/+2
When allocating as an array of char only alignment of 1 is guaranteed but the structure needs an alignment of 8. Specify alignment explicitly
2024-11-21Reallocate fuse_session buffer transparently for extended max writesJoanne Koong-31/+29
A previous PR supported extended max writes (eg write requests larger than 1 MB) by initializing the fuse session buffer size to use the max_pages_limit set in /proc/sys/fs/fuse. However, this is a huge problem for machines where multiple fuse servers may be running but only one server needs large writes. In this case, a lot of memory will be wasted and will lead to OOM issues. This PR does a reallocation of the session buffer transparently if the server set "se->conn.max_write" to a value larger than 1 MiB. This is only for buffers that are "owned" by libfuse - if the server wishes to provide its own allocated buffer for receiving/processing requests, then it should ensure that buffer is allocated to the proper size from the start. Local testing showed: echo 65535 | sudo tee /proc/sys/fs/fuse/max_pages_limit dd if=/dev/urandom of=hello_file bs=6M count=2 write requests: write request size is 5242880 write request size is 1048576 write request size is 5242880 write request size is 1048576
2024-11-13Add FUSE_CAP_NO_EXPORT and use it in passthrough_hpBernd Schubert-0/+4
This should stop some more xfstest test failures.
2024-11-13Add fuse_set_feature_flag() / fuse_unset_feature_flagBernd Schubert-4/+14
Simplify setting feature flags a bit by adding a helper function. Also move the check for valid flags into a funtion we can re-use in a later patch.