]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
gpio: convert linehandle_create() to FD_PREPARE()
authorChristian Brauner <brauner@kernel.org>
Mon, 24 Nov 2025 12:55:02 +0000 (13:55 +0100)
committerChristian Brauner <brauner@kernel.org>
Fri, 28 Nov 2025 11:42:35 +0000 (12:42 +0100)
Link: https://patch.msgid.link/20251123-work-fd-prepare-v4-38-b6efa1706cfd@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
drivers/gpio/gpiolib-cdev.c

index 175836467f216ae372a2cb6e2cd68c7867534938..675640f6360ecfdac25146e568ede564698874fe 100644 (file)
@@ -298,12 +298,13 @@ static const struct file_operations linehandle_fileops = {
 #endif
 };
 
+DEFINE_FREE(linehandle_free, struct linehandle_state *, if (!IS_ERR_OR_NULL(_T)) linehandle_free(_T))
+
 static int linehandle_create(struct gpio_device *gdev, void __user *ip)
 {
        struct gpiohandle_request handlereq;
-       struct linehandle_state *lh;
-       struct file *file;
-       int fd, i, ret;
+       struct linehandle_state *lh __free(linehandle_free) = NULL;
+       int i, ret;
        u32 lflags;
 
        if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -327,10 +328,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                lh->label = kstrndup(handlereq.consumer_label,
                                     sizeof(handlereq.consumer_label) - 1,
                                     GFP_KERNEL);
-               if (!lh->label) {
-                       ret = -ENOMEM;
-                       goto out_free_lh;
-               }
+               if (!lh->label)
+                       return -ENOMEM;
        }
 
        lh->num_descs = handlereq.lines;
@@ -340,20 +339,18 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                u32 offset = handlereq.lineoffsets[i];
                struct gpio_desc *desc = gpio_device_get_desc(gdev, offset);
 
-               if (IS_ERR(desc)) {
-                       ret = PTR_ERR(desc);
-                       goto out_free_lh;
-               }
+               if (IS_ERR(desc))
+                       return PTR_ERR(desc);
 
                ret = gpiod_request_user(desc, lh->label);
                if (ret)
-                       goto out_free_lh;
+                       return ret;
                lh->descs[i] = desc;
                linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
 
                ret = gpiod_set_transitory(desc, false);
                if (ret < 0)
-                       goto out_free_lh;
+                       return ret;
 
                /*
                 * Lines have to be requested explicitly for input
@@ -364,11 +361,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
 
                        ret = gpiod_direction_output_nonotify(desc, val);
                        if (ret)
-                               goto out_free_lh;
+                               return ret;
                } else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
                        ret = gpiod_direction_input_nonotify(desc);
                        if (ret)
-                               goto out_free_lh;
+                               return ret;
                }
 
                gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
@@ -377,44 +374,23 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                        offset);
        }
 
-       fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
-       if (fd < 0) {
-               ret = fd;
-               goto out_free_lh;
-       }
+       FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
+                  anon_inode_getfile("gpio-linehandle", &linehandle_fileops,
+                                     lh, O_RDONLY | O_CLOEXEC));
+       if (fdf.err)
+               return fdf.err;
+       retain_and_null_ptr(lh);
 
-       file = anon_inode_getfile("gpio-linehandle",
-                                 &linehandle_fileops,
-                                 lh,
-                                 O_RDONLY | O_CLOEXEC);
-       if (IS_ERR(file)) {
-               ret = PTR_ERR(file);
-               goto out_put_unused_fd;
-       }
-
-       handlereq.fd = fd;
-       if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
-               /*
-                * fput() will trigger the release() callback, so do not go onto
-                * the regular error cleanup path here.
-                */
-               fput(file);
-               put_unused_fd(fd);
+       handlereq.fd = fd_prepare_fd(fdf);
+       if (copy_to_user(ip, &handlereq, sizeof(handlereq)))
                return -EFAULT;
-       }
 
-       fd_install(fd, file);
+       fd_publish(fdf);
 
        dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
                lh->num_descs);
 
        return 0;
-
-out_put_unused_fd:
-       put_unused_fd(fd);
-out_free_lh:
-       linehandle_free(lh);
-       return ret;
 }
 #endif /* CONFIG_GPIO_CDEV_V1 */