aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernd Schubert <bschubert@ddn.com>2025-03-07 22:43:50 +0100
committerBernd Schubert <bernd@bsbernd.com>2025-03-14 12:58:14 +0100
commit065272a23392011ea1728c4f2d20e63cf6579e7d (patch)
tree48834b949e6767f62ff7023093e6767ff831b9e3
parent3ae5ca7443348aabad9bc71b9d5b0999f8292379 (diff)
downloadlibfuse-065272a23392011ea1728c4f2d20e63cf6579e7d.tar.gz
fuse_session_receive_buf: Fix the pipe buf size
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>
-rw-r--r--lib/fuse_i.h4
-rw-r--r--lib/fuse_lowlevel.c12
2 files changed, 13 insertions, 3 deletions
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index ea04c34..69ca159 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -72,14 +72,14 @@ struct fuse_session {
int broken_splice_nonblock;
uint64_t notify_ctr;
struct fuse_notify_req notify_list;
- size_t bufsize;
+ _Atomic size_t bufsize;
int error;
/* This is useful if any kind of ABI incompatibility is found at
* a later version, to 'fix' it at run time.
*/
struct libfuse_version version;
- bool buf_reallocable;
+ _Atomic bool buf_reallocable;
};
struct fuse_chan {
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index d650944..0642572 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -3042,11 +3042,14 @@ static int _fuse_session_receive_buf(struct fuse_session *se,
{
int err;
ssize_t res;
- size_t bufsize = se->bufsize;
+ size_t bufsize;
#ifdef HAVE_SPLICE
struct fuse_ll_pipe *llp;
struct fuse_buf tmpbuf;
+pipe_retry:
+ bufsize = se->bufsize;
+
if (se->conn.proto_minor < 14 ||
!(se->conn.want_ext & FUSE_CAP_SPLICE_READ))
goto fallback;
@@ -3091,6 +3094,13 @@ static int _fuse_session_receive_buf(struct fuse_session *se,
fuse_session_exit(se);
return 0;
}
+
+ /* FUSE_INIT might have increased the required bufsize */
+ if (err == EINVAL && bufsize < se->bufsize) {
+ fuse_ll_clear_pipe(se);
+ goto pipe_retry;
+ }
+
if (err != EINTR && err != EAGAIN)
perror("fuse: splice from device");
return -err;