fuse: simplify fuse_dev_ioctl_clone()

Don't need to check if the new device file is already initialized, since
fuse_dev_install_with_pq() will do that anyway.

Make fuse_dev_install_with_pq() return a boolean value indicating success so
that fuse_dev_ioctl_clone() can return an error in case of failure.

Move aborting the connection (setting fc->connected to zero) to
fuse_dev_install(), because it is not needed when the clone ioctl fails.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Miklos Szeredi 2026-04-02 22:57:49 +02:00
parent 48649c0603
commit a636077231

View File

@ -454,12 +454,15 @@ struct fuse_dev *fuse_dev_alloc(void)
}
EXPORT_SYMBOL_GPL(fuse_dev_alloc);
static void fuse_dev_install_with_pq(struct fuse_dev *fud, struct fuse_chan *fch,
/*
* Installs @fch into @fud, return true on success. "Consumes" @pq in either case.
*/
static bool fuse_dev_install_with_pq(struct fuse_dev *fud, struct fuse_chan *fch,
struct list_head *pq)
{
struct fuse_chan *old_fch;
spin_lock(&fch->lock);
guard(spinlock)(&fch->lock);
/*
* Pairs with:
* - xchg() in fuse_dev_release()
@ -472,18 +475,17 @@ static void fuse_dev_install_with_pq(struct fuse_dev *fud, struct fuse_chan *fch
* - it was already set to a different fc
* - it was set to disconneted
*/
fch->connected = 0;
kfree(pq);
} else {
if (pq) {
WARN_ON(fud->pq.processing);
fud->pq.processing = pq;
}
list_add_tail(&fud->entry, &fch->devices);
fuse_conn_get(fch->conn);
wake_up_all(&fuse_dev_waitq);
return false;
}
spin_unlock(&fch->lock);
if (pq) {
WARN_ON(fud->pq.processing);
fud->pq.processing = pq;
}
list_add_tail(&fud->entry, &fch->devices);
fuse_conn_get(fch->conn);
wake_up_all(&fuse_dev_waitq);
return true;
}
void fuse_dev_install(struct fuse_dev *fud, struct fuse_chan *fch)
@ -491,7 +493,10 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_chan *fch)
struct list_head *pq = fch->pq_prealloc;
fch->pq_prealloc = NULL;
fuse_dev_install_with_pq(fud, fch, pq);
if (!fuse_dev_install_with_pq(fud, fch, pq)) {
/* Channel is not usable without a dev */
fuse_chan_abort(fch, false);
}
}
EXPORT_SYMBOL_GPL(fuse_dev_install);
@ -2297,15 +2302,13 @@ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
if (IS_ERR(fud))
return PTR_ERR(fud);
new_fud = fuse_file_to_fud(file);
if (fuse_dev_chan_get(new_fud))
return -EINVAL;
pq = fuse_pqueue_alloc();
if (!pq)
return -ENOMEM;
fuse_dev_install_with_pq(new_fud, fud->chan, pq);
new_fud = fuse_file_to_fud(file);
if (!fuse_dev_install_with_pq(new_fud, fud->chan, pq))
return -EINVAL;
return 0;
}