]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fuse_ctl_add_conn(): fix nlink breakage in case of early failure
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 26 Oct 2025 06:38:43 +0000 (02:38 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 16 Nov 2025 06:35:01 +0000 (01:35 -0500)
fuse_ctl_remove_conn() used to decrement the link count of root
manually; that got subsumed by simple_recursive_removal(), but
in case when subdirectory creation has failed the latter won't
get called.

Just move the modification of parent's link count into
fuse_ctl_add_dentry() to keep the things simple.  Allows to
get rid of the nlink argument as well...

Fixes: fcaac5b42768 "fuse_ctl: use simple_recursive_removal()"
Acked-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/fuse/control.c

index bb407705603c295159692e75599bf5289e1e5ea7..5247df896c5d016dd2dfa589f7967ab1ccbc2faf 100644 (file)
@@ -205,8 +205,7 @@ static const struct file_operations fuse_conn_congestion_threshold_ops = {
 
 static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
                                          struct fuse_conn *fc,
-                                         const char *name,
-                                         int mode, int nlink,
+                                         const char *name, int mode,
                                          const struct inode_operations *iop,
                                          const struct file_operations *fop)
 {
@@ -232,7 +231,10 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
        if (iop)
                inode->i_op = iop;
        inode->i_fop = fop;
-       set_nlink(inode, nlink);
+       if (S_ISDIR(mode)) {
+               inc_nlink(d_inode(parent));
+               inc_nlink(inode);
+       }
        inode->i_private = fc;
        d_add(dentry, inode);
 
@@ -252,22 +254,21 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
                return 0;
 
        parent = fuse_control_sb->s_root;
-       inc_nlink(d_inode(parent));
        sprintf(name, "%u", fc->dev);
-       parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
+       parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500,
                                     &simple_dir_inode_operations,
                                     &simple_dir_operations);
        if (!parent)
                goto err;
 
-       if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
+       if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400,
                                 NULL, &fuse_ctl_waiting_ops) ||
-           !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
+           !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200,
                                 NULL, &fuse_ctl_abort_ops) ||
            !fuse_ctl_add_dentry(parent, fc, "max_background", S_IFREG | 0600,
-                                1, NULL, &fuse_conn_max_background_ops) ||
+                                NULL, &fuse_conn_max_background_ops) ||
            !fuse_ctl_add_dentry(parent, fc, "congestion_threshold",
-                                S_IFREG | 0600, 1, NULL,
+                                S_IFREG | 0600, NULL,
                                 &fuse_conn_congestion_threshold_ops))
                goto err;