* [RFC PATCH 0/3] fuse: fix hang with sync init
@ 2026-03-11 21:51 Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 1/3] fuse: create fuse_dev on /dev/fuse open instead of mount Miklos Szeredi
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Miklos Szeredi @ 2026-03-11 21:51 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Bernd Schubert
This is a first cut, with minimal testing or polish.
Code snippet from the test server:
static void *lo_mount_thread(void *data)
{
struct lo_data *lo = data;
int fs_fd, mnt_fd;
char opt[64];
ER(unshare(CLONE_FILES));
fs_fd = ER(fsopen("fuse", 0));
snprintf(opt, sizeof(opt), "%i", lo->devfd);
ER(fsconfig(fs_fd, FSCONFIG_SET_STRING, "fd", opt, 0));
close(lo->devfd);
ER(fsconfig(fs_fd, FSCONFIG_SET_STRING, "rootmode", "40000", 0));
ER(fsconfig(fs_fd, FSCONFIG_SET_STRING, "user_id", "0", 0));
ER(fsconfig(fs_fd, FSCONFIG_SET_STRING, "group_id", "0", 0));
ER(fsconfig(fs_fd, FSCONFIG_CMD_CREATE, 0, 0, 0));
mnt_fd = ER(fsmount(fs_fd, 0, 0));
ER(move_mount(mnt_fd, "", AT_FDCWD, lo->c.mnt, MOVE_MOUNT_F_EMPTY_PATH));
close(mnt_fd);
close(fs_fd);
return NULL;
}
int main(int argc, char *argv[])
{
/* ... */
if (ioctl(lo->devfd, FUSE_DEV_IOC_SYNC_INIT) == 0)
lo_start_threads(lo);
else
/* ... */
pthread_t id;
PE(pthread_create(&id, NULL, lo_mount_thread, lo));
PE(pthread_join(id, NULL));
/* ... */
}
---
Miklos Szeredi (3):
fuse: create fuse_dev on /dev/fuse open instead of mount
fuse: add refcount to fuse_dev
fuse: don't require /dev/fuse fd to be kept open during mount
fs/fuse/cuse.c | 2 +-
fs/fuse/dev.c | 48 +++++++++-------------
fs/fuse/fuse_dev_i.h | 15 +++----
fs/fuse/fuse_i.h | 13 +++---
fs/fuse/inode.c | 96 ++++++++++++++++++++++----------------------
fs/fuse/virtio_fs.c | 4 +-
6 files changed, 83 insertions(+), 95 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 1/3] fuse: create fuse_dev on /dev/fuse open instead of mount
2026-03-11 21:51 [RFC PATCH 0/3] fuse: fix hang with sync init Miklos Szeredi
@ 2026-03-11 21:51 ` Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 2/3] fuse: add refcount to fuse_dev Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount Miklos Szeredi
2 siblings, 0 replies; 5+ messages in thread
From: Miklos Szeredi @ 2026-03-11 21:51 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Bernd Schubert
Will need this later so the /dev/fuse open file reference is not held
during FSCONFIG_CMD_CREATE.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/fuse/dev.c | 48 ++++++++++++++++++--------------------------
fs/fuse/fuse_dev_i.h | 15 +++++++-------
fs/fuse/fuse_i.h | 5 ++---
fs/fuse/inode.c | 33 ++++++++++--------------------
fs/fuse/virtio_fs.c | 2 --
5 files changed, 40 insertions(+), 63 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 2c16b94357d5..d114869d6900 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1542,32 +1542,24 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
static int fuse_dev_open(struct inode *inode, struct file *file)
{
- /*
- * The fuse device's file's private_data is used to hold
- * the fuse_conn(ection) when it is mounted, and is used to
- * keep track of whether the file has been mounted already.
- */
- file->private_data = NULL;
+ struct fuse_dev *fud = fuse_dev_alloc();
+
+ if (!fud)
+ return -ENOMEM;
+
+ file->private_data = fud;
return 0;
}
struct fuse_dev *fuse_get_dev(struct file *file)
{
- struct fuse_dev *fud = __fuse_get_dev(file);
+ struct fuse_dev *fud = file->private_data;
int err;
- if (likely(fud))
- return fud;
-
- err = wait_event_interruptible(fuse_dev_waitq,
- READ_ONCE(file->private_data) != FUSE_DEV_SYNC_INIT);
+ err = wait_event_interruptible(fuse_dev_waitq, smp_load_acquire(&fud->fc));
if (err)
return ERR_PTR(err);
- fud = __fuse_get_dev(file);
- if (!fud)
- return ERR_PTR(-EPERM);
-
return fud;
}
@@ -2534,10 +2526,10 @@ void fuse_wait_aborted(struct fuse_conn *fc)
int fuse_dev_release(struct inode *inode, struct file *file)
{
- struct fuse_dev *fud = __fuse_get_dev(file);
+ struct fuse_dev *fud = file->private_data;
+ struct fuse_conn *fc = smp_load_acquire(&fud->fc);
- if (fud) {
- struct fuse_conn *fc = fud->fc;
+ if (fc) {
struct fuse_pqueue *fpq = &fud->pq;
LIST_HEAD(to_end);
unsigned int i;
@@ -2555,8 +2547,8 @@ int fuse_dev_release(struct inode *inode, struct file *file)
WARN_ON(fc->iq.fasync != NULL);
fuse_abort_conn(fc);
}
- fuse_dev_free(fud);
}
+ fuse_dev_free(fud);
return 0;
}
EXPORT_SYMBOL_GPL(fuse_dev_release);
@@ -2574,16 +2566,13 @@ static int fuse_dev_fasync(int fd, struct file *file, int on)
static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
{
- struct fuse_dev *fud;
+ struct fuse_dev *fud = new->private_data;
- if (__fuse_get_dev(new))
+ if (fud->fc)
return -EINVAL;
- fud = fuse_dev_alloc_install(fc);
- if (!fud)
- return -ENOMEM;
-
- new->private_data = fud;
+ fuse_dev_install(fud, fc);
+ smp_store_release(&fud->fc, fc);
atomic_inc(&fc->dev_count);
return 0;
@@ -2657,10 +2646,11 @@ static long fuse_dev_ioctl_backing_close(struct file *file, __u32 __user *argp)
static long fuse_dev_ioctl_sync_init(struct file *file)
{
int err = -EINVAL;
+ struct fuse_dev *fud = file->private_data;
mutex_lock(&fuse_mutex);
- if (!__fuse_get_dev(file)) {
- WRITE_ONCE(file->private_data, FUSE_DEV_SYNC_INIT);
+ if (!fud->fc) {
+ fud->sync_init = true;
err = 0;
}
mutex_unlock(&fuse_mutex);
diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h
index 134bf44aff0d..3db39590fbda 100644
--- a/fs/fuse/fuse_dev_i.h
+++ b/fs/fuse/fuse_dev_i.h
@@ -39,18 +39,19 @@ struct fuse_copy_state {
} ring;
};
-#define FUSE_DEV_SYNC_INIT ((struct fuse_dev *) 1)
-#define FUSE_DEV_PTR_MASK (~1UL)
-
static inline struct fuse_dev *__fuse_get_dev(struct file *file)
{
+ struct fuse_dev *fud = file->private_data;
+ struct fuse_conn *fc = smp_load_acquire(&fud->fc);
+
/*
- * Lockless access is OK, because file->private data is set
- * once during mount and is valid until the file is released.
+ * Lockless access is OK, because fud->fc is set once during mount and
+ * is valid until the file is released.
*/
- struct fuse_dev *fud = READ_ONCE(file->private_data);
+ if (!fc)
+ return NULL;
- return (typeof(fud)) ((unsigned long) fud & FUSE_DEV_PTR_MASK);
+ return fud;
}
struct fuse_dev *fuse_get_dev(struct file *file);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 7f16049387d1..739220d96b6f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -576,6 +576,8 @@ struct fuse_pqueue {
* Fuse device instance
*/
struct fuse_dev {
+ bool sync_init;
+
/** Fuse connection for this device */
struct fuse_conn *fc;
@@ -622,9 +624,6 @@ struct fuse_fs_context {
/* DAX device, may be NULL */
struct dax_device *dax_dev;
-
- /* fuse_dev pointer to fill in, should contain NULL on entry */
- void **fudptr;
};
struct fuse_sync_bucket {
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e57b8af06be9..92f56bd6ac23 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1822,7 +1822,7 @@ EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
{
- struct fuse_dev *fud = NULL;
+ struct fuse_dev *fud = ctx->file ? ctx->file->private_data : NULL;
struct fuse_mount *fm = get_fuse_mount_super(sb);
struct fuse_conn *fc = fm->fc;
struct inode *root;
@@ -1856,18 +1856,11 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
goto err;
}
- if (ctx->fudptr) {
- err = -ENOMEM;
- fud = fuse_dev_alloc_install(fc);
- if (!fud)
- goto err_free_dax;
- }
-
fc->dev = sb->s_dev;
fm->sb = sb;
err = fuse_bdi_init(fc, sb);
if (err)
- goto err_dev_free;
+ goto err_free_dax;
/* Handle umasking inside the fuse code */
if (sb->s_flags & SB_POSIXACL)
@@ -1889,15 +1882,15 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
set_default_d_op(sb, &fuse_dentry_operations);
root_dentry = d_make_root(root);
if (!root_dentry)
- goto err_dev_free;
+ goto err_free_dax;
mutex_lock(&fuse_mutex);
err = -EINVAL;
- if (ctx->fudptr && *ctx->fudptr) {
- if (*ctx->fudptr == FUSE_DEV_SYNC_INIT)
- fc->sync_init = 1;
- else
+ if (fud) {
+ if (fud->fc)
goto err_unlock;
+ if (fud->sync_init)
+ fc->sync_init = 1;
}
err = fuse_ctl_add_conn(fc);
@@ -1906,19 +1899,18 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
list_add_tail(&fc->entry, &fuse_conn_list);
sb->s_root = root_dentry;
- if (ctx->fudptr) {
- *ctx->fudptr = fud;
+ if (fud) {
+ fuse_dev_install(fud, fc);
+ smp_store_release(&fud->fc, fc);
wake_up_all(&fuse_dev_waitq);
}
+
mutex_unlock(&fuse_mutex);
return 0;
err_unlock:
mutex_unlock(&fuse_mutex);
dput(root_dentry);
- err_dev_free:
- if (fud)
- fuse_dev_free(fud);
err_free_dax:
if (IS_ENABLED(CONFIG_FUSE_DAX))
fuse_dax_conn_free(fc);
@@ -1944,13 +1936,10 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
if ((ctx->file->f_op != &fuse_dev_operations) ||
(ctx->file->f_cred->user_ns != sb->s_user_ns))
return -EINVAL;
- ctx->fudptr = &ctx->file->private_data;
err = fuse_fill_super_common(sb, ctx);
if (err)
return err;
- /* file->private_data shall be visible on all CPUs after this */
- smp_mb();
fm = get_fuse_mount_super(sb);
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 2f7485ffac52..f685916754ad 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -1590,8 +1590,6 @@ static int virtio_fs_fill_super(struct super_block *sb, struct fs_context *fsc)
goto err_free_fuse_devs;
}
- /* virtiofs allocates and installs its own fuse devices */
- ctx->fudptr = NULL;
if (ctx->dax_mode != FUSE_DAX_NEVER) {
if (ctx->dax_mode == FUSE_DAX_ALWAYS && !fs->dax_dev) {
err = -EINVAL;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [RFC PATCH 2/3] fuse: add refcount to fuse_dev
2026-03-11 21:51 [RFC PATCH 0/3] fuse: fix hang with sync init Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 1/3] fuse: create fuse_dev on /dev/fuse open instead of mount Miklos Szeredi
@ 2026-03-11 21:51 ` Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount Miklos Szeredi
2 siblings, 0 replies; 5+ messages in thread
From: Miklos Szeredi @ 2026-03-11 21:51 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Bernd Schubert
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/fuse/cuse.c | 2 +-
fs/fuse/dev.c | 2 +-
fs/fuse/fuse_i.h | 4 +++-
fs/fuse/inode.c | 11 ++++++++---
fs/fuse/virtio_fs.c | 2 +-
5 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index dfcb98a654d8..174333633471 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -527,7 +527,7 @@ static int cuse_channel_open(struct inode *inode, struct file *file)
cc->fc.initialized = 1;
rc = cuse_send_init(cc);
if (rc) {
- fuse_dev_free(fud);
+ fuse_dev_put(fud);
return rc;
}
file->private_data = fud;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index d114869d6900..69868f851e13 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2548,7 +2548,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
fuse_abort_conn(fc);
}
}
- fuse_dev_free(fud);
+ fuse_dev_put(fud);
return 0;
}
EXPORT_SYMBOL_GPL(fuse_dev_release);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 739220d96b6f..0817fbe3ba43 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -576,6 +576,8 @@ struct fuse_pqueue {
* Fuse device instance
*/
struct fuse_dev {
+ refcount_t ref;
+
bool sync_init;
/** Fuse connection for this device */
@@ -1342,7 +1344,7 @@ void fuse_conn_put(struct fuse_conn *fc);
struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc);
struct fuse_dev *fuse_dev_alloc(void);
void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc);
-void fuse_dev_free(struct fuse_dev *fud);
+void fuse_dev_put(struct fuse_dev *fud);
int fuse_send_init(struct fuse_mount *fm);
/**
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 92f56bd6ac23..5a823b574634 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1622,6 +1622,7 @@ struct fuse_dev *fuse_dev_alloc(void)
if (!fud)
return NULL;
+ refcount_set(&fud->ref, 1);
pq = kzalloc_objs(struct list_head, FUSE_PQ_HASH_SIZE);
if (!pq) {
kfree(fud);
@@ -1657,10 +1658,14 @@ struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc)
}
EXPORT_SYMBOL_GPL(fuse_dev_alloc_install);
-void fuse_dev_free(struct fuse_dev *fud)
+void fuse_dev_put(struct fuse_dev *fud)
{
- struct fuse_conn *fc = fud->fc;
+ struct fuse_conn *fc;
+
+ if (!refcount_dec_and_test(&fud->ref))
+ return;
+ fc = smp_load_acquire(&fud->fc);
if (fc) {
spin_lock(&fc->lock);
list_del(&fud->entry);
@@ -1671,7 +1676,7 @@ void fuse_dev_free(struct fuse_dev *fud)
kfree(fud->pq.processing);
kfree(fud);
}
-EXPORT_SYMBOL_GPL(fuse_dev_free);
+EXPORT_SYMBOL_GPL(fuse_dev_put);
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
const struct fuse_inode *fi)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index f685916754ad..12300651a0f1 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -486,7 +486,7 @@ static void virtio_fs_free_devs(struct virtio_fs *fs)
if (!fsvq->fud)
continue;
- fuse_dev_free(fsvq->fud);
+ fuse_dev_put(fsvq->fud);
fsvq->fud = NULL;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount
2026-03-11 21:51 [RFC PATCH 0/3] fuse: fix hang with sync init Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 1/3] fuse: create fuse_dev on /dev/fuse open instead of mount Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 2/3] fuse: add refcount to fuse_dev Miklos Szeredi
@ 2026-03-11 21:51 ` Miklos Szeredi
2026-03-12 9:56 ` Stef Bon
2 siblings, 1 reply; 5+ messages in thread
From: Miklos Szeredi @ 2026-03-11 21:51 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Bernd Schubert
With the new mount API the sequence of syscalls would be:
fs_fd = fsopen("fuse", 0);
snprintf(opt, sizeof(opt), "%i", devfd);
fsconfig(fs_fd, FSCONFIG_SET_STRING, "fd", opt, 0);
/* ... */
fsconfig(fs_fd, FSCONFIG_CMD_CREATE, 0, 0, 0);
Current mount code just stores the value of devfd in the fs_context and
uses it in during FSCONFIG_CMD_CREATE.
This is not very elegant, but there's a bigger problem: when sync init is
used and the server exits for some reason (error, crash) while processing
FUSE_INIT, the filesystem creation will hang. The reason is that while all
other threads will exit, the mounting thread (or process) will keep the
device fd open, which will prevent an abort from happening.
This is a regression from the async mount case, where the mount was done
first, and the FUSE_INIT processing afterwards, in which case there's no
such recursive syscall keeping the fd open.
The solution is twofold:
a) use unshare(CLONE_FILES) in the mounting thread and close the device fd
after fsconfig(fs_fd, FSCONFIG_SET_STRING, "fd", ...)
b) only reference the fuse_dev from fs_context not the device file itself
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/fuse/fuse_i.h | 4 +---
fs/fuse/inode.c | 54 +++++++++++++++++++++++++++---------------------
2 files changed, 31 insertions(+), 27 deletions(-)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0817fbe3ba43..356cb4bafb01 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -603,13 +603,11 @@ static inline bool fuse_is_inode_dax_mode(enum fuse_dax_mode mode)
}
struct fuse_fs_context {
- int fd;
- struct file *file;
+ struct fuse_dev *fud;
unsigned int rootmode;
kuid_t user_id;
kgid_t group_id;
bool is_bdev:1;
- bool fd_present:1;
bool rootmode_present:1;
bool user_id_present:1;
bool group_id_present:1;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 5a823b574634..17f4e1d30222 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -800,6 +800,26 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
{}
};
+static int fuse_opt_fd(struct fs_context *fsc, int fd)
+{
+ struct file *file __free(fput) = fget(fd);
+ struct fuse_fs_context *ctx = fsc->fs_private;
+
+ if (file->f_op != &fuse_dev_operations)
+ return invalfc(fsc, "fd is not a fuse device");
+ /*
+ * Require mount to happen from the same user namespace which
+ * opened /dev/fuse to prevent potential attacks.
+ */
+ if (file->f_cred->user_ns != fsc->user_ns)
+ return invalfc(fsc, "wrong user namespace for fuse device");
+
+ ctx->fud = file->private_data;
+ refcount_inc(&ctx->fud->ref);
+
+ return 0;
+}
+
static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
{
struct fs_parse_result result;
@@ -839,9 +859,7 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
return 0;
case OPT_FD:
- ctx->fd = result.uint_32;
- ctx->fd_present = true;
- break;
+ return fuse_opt_fd(fsc, result.uint_32);
case OPT_ROOTMODE:
if (!fuse_valid_type(result.uint_32))
@@ -904,6 +922,8 @@ static void fuse_free_fsc(struct fs_context *fsc)
struct fuse_fs_context *ctx = fsc->fs_private;
if (ctx) {
+ if (ctx->fud)
+ fuse_dev_put(ctx->fud);
kfree(ctx->subtype);
kfree(ctx);
}
@@ -1827,7 +1847,7 @@ EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
{
- struct fuse_dev *fud = ctx->file ? ctx->file->private_data : NULL;
+ struct fuse_dev *fud = ctx->fud;
struct fuse_mount *fm = get_fuse_mount_super(sb);
struct fuse_conn *fc = fm->fc;
struct inode *root;
@@ -1930,18 +1950,10 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
struct fuse_mount *fm;
int err;
- if (!ctx->file || !ctx->rootmode_present ||
+ if (!ctx->fud || !ctx->rootmode_present ||
!ctx->user_id_present || !ctx->group_id_present)
return -EINVAL;
- /*
- * Require mount to happen from the same user namespace which
- * opened /dev/fuse to prevent potential attacks.
- */
- if ((ctx->file->f_op != &fuse_dev_operations) ||
- (ctx->file->f_cred->user_ns != sb->s_user_ns))
- return -EINVAL;
-
err = fuse_fill_super_common(sb, ctx);
if (err)
return err;
@@ -1969,8 +1981,7 @@ static int fuse_test_super(struct super_block *sb, struct fs_context *fsc)
static int fuse_get_tree(struct fs_context *fsc)
{
struct fuse_fs_context *ctx = fsc->fs_private;
- struct fuse_dev *fud;
- struct fuse_conn *fc;
+ struct fuse_conn *fc, *key;
struct fuse_mount *fm;
struct super_block *sb;
int err;
@@ -1990,9 +2001,6 @@ static int fuse_get_tree(struct fs_context *fsc)
fsc->s_fs_info = fm;
- if (ctx->fd_present)
- ctx->file = fget(ctx->fd);
-
if (IS_ENABLED(CONFIG_BLOCK) && ctx->is_bdev) {
err = get_tree_bdev(fsc, fuse_fill_super);
goto out;
@@ -2002,16 +2010,16 @@ static int fuse_get_tree(struct fs_context *fsc)
* (found by device name), normal fuse mounts can't
*/
err = -EINVAL;
- if (!ctx->file)
+ if (!ctx->fud)
goto out;
/*
* Allow creating a fuse mount with an already initialized fuse
* connection
*/
- fud = __fuse_get_dev(ctx->file);
- if (ctx->file->f_op == &fuse_dev_operations && fud) {
- fsc->sget_key = fud->fc;
+ key = smp_load_acquire(&ctx->fud->fc);
+ if (key) {
+ fsc->sget_key = key;
sb = sget_fc(fsc, fuse_test_super, fuse_set_no_super);
err = PTR_ERR_OR_ZERO(sb);
if (!IS_ERR(sb))
@@ -2022,8 +2030,6 @@ static int fuse_get_tree(struct fs_context *fsc)
out:
if (fsc->s_fs_info)
fuse_mount_destroy(fm);
- if (ctx->file)
- fput(ctx->file);
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount
2026-03-11 21:51 ` [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount Miklos Szeredi
@ 2026-03-12 9:56 ` Stef Bon
0 siblings, 0 replies; 5+ messages in thread
From: Stef Bon @ 2026-03-12 9:56 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-fsdevel, Bernd Schubert
Op wo 11 mrt 2026 om 22:51 schreef Miklos Szeredi <mszeredi@redhat.com>:
>
> With the new mount API the sequence of syscalls would be:
>
> fs_fd = fsopen("fuse", 0);
> snprintf(opt, sizeof(opt), "%i", devfd);
I'm not sure this is real code or just an example, but should the
fs_fd and devfd be the same?
S. Bon
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-12 9:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 21:51 [RFC PATCH 0/3] fuse: fix hang with sync init Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 1/3] fuse: create fuse_dev on /dev/fuse open instead of mount Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 2/3] fuse: add refcount to fuse_dev Miklos Szeredi
2026-03-11 21:51 ` [RFC PATCH 3/3] fuse: don't require /dev/fuse fd to be kept open during mount Miklos Szeredi
2026-03-12 9:56 ` Stef Bon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox