From: Kent Gibson Date: Mon, 16 Feb 2026 12:37:09 +0000 (+0800) Subject: gpio: cdev: convert lineevent_create() and linereq_create() to FD_PREPARE() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=96c02c906a44bc280ef26e343126dd3349d8cae9;p=thirdparty%2Flinux.git gpio: cdev: convert lineevent_create() and linereq_create() to FD_PREPARE() linehandle_create() was recently converted to use FD_PREPARE() to simplify fd creation and cleanup logic. Apply the equivalent conversion to lineevent_create() and linereq_create(). Signed-off-by: Kent Gibson Link: https://patch.msgid.link/20260216123709.281444-1-warthog618@gmail.com Signed-off-by: Bartosz Golaszewski --- diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 73ae77f0f2133..c919ec0d0a660 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1586,15 +1586,16 @@ static const struct file_operations line_fileops = { #endif }; +DEFINE_FREE(linereq_free, struct linereq *, if (!IS_ERR_OR_NULL(_T)) linereq_free(_T)) + static int linereq_create(struct gpio_device *gdev, void __user *ip) { struct gpio_v2_line_request ulr; struct gpio_v2_line_config *lc; - struct linereq *lr; - struct file *file; + struct linereq *lr __free(linereq_free) = NULL; u64 flags, edflags; unsigned int i; - int fd, ret; + int ret; if (copy_from_user(&ulr, ip, sizeof(ulr))) return -EFAULT; @@ -1627,10 +1628,8 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) /* label is only initialized if consumer is set */ lr->label = kstrndup(ulr.consumer, sizeof(ulr.consumer) - 1, GFP_KERNEL); - if (!lr->label) { - ret = -ENOMEM; - goto out_free_linereq; - } + if (!lr->label) + return -ENOMEM; } mutex_init(&lr->config_mutex); @@ -1649,14 +1648,12 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) u32 offset = ulr.offsets[i]; struct gpio_desc *desc = gpio_device_get_desc(gdev, offset); - if (IS_ERR(desc)) { - ret = PTR_ERR(desc); - goto out_free_linereq; - } + if (IS_ERR(desc)) + return PTR_ERR(desc); ret = gpiod_request_user(desc, lr->label); if (ret) - goto out_free_linereq; + return ret; lr->lines[i].desc = desc; flags = gpio_v2_line_config_flags(lc, i); @@ -1664,7 +1661,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) ret = gpiod_set_transitory(desc, false); if (ret < 0) - goto out_free_linereq; + return ret; edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS; /* @@ -1676,16 +1673,16 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) ret = gpiod_direction_output_nonotify(desc, val); if (ret) - goto out_free_linereq; + return ret; } else if (flags & GPIO_V2_LINE_FLAG_INPUT) { ret = gpiod_direction_input_nonotify(desc); if (ret) - goto out_free_linereq; + return ret; ret = edge_detector_setup(&lr->lines[i], lc, i, edflags); if (ret) - goto out_free_linereq; + return ret; } lr->lines[i].edflags = edflags; @@ -1700,44 +1697,25 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) ret = blocking_notifier_chain_register(&gdev->device_notifier, &lr->device_unregistered_nb); if (ret) - goto out_free_linereq; - - fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); - if (fd < 0) { - ret = fd; - goto out_free_linereq; - } + return ret; - file = anon_inode_getfile("gpio-line", &line_fileops, lr, - O_RDONLY | O_CLOEXEC); - if (IS_ERR(file)) { - ret = PTR_ERR(file); - goto out_put_unused_fd; - } + FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, + anon_inode_getfile("gpio-line", &line_fileops, lr, + O_RDONLY | O_CLOEXEC)); + if (fdf.err) + return fdf.err; + retain_and_null_ptr(lr); - ulr.fd = fd; - if (copy_to_user(ip, &ulr, sizeof(ulr))) { - /* - * fput() will trigger the release() callback, so do not go onto - * the regular error cleanup path here. - */ - fput(file); - put_unused_fd(fd); + ulr.fd = fd_prepare_fd(fdf); + if (copy_to_user(ip, &ulr, sizeof(ulr))) return -EFAULT; - } - fd_install(fd, file); + fd_publish(fdf); dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", - lr->num_lines); + ulr.num_lines); return 0; - -out_put_unused_fd: - put_unused_fd(fd); -out_free_linereq: - linereq_free(lr); - return ret; } #ifdef CONFIG_GPIO_CDEV_V1 @@ -2010,16 +1988,16 @@ static irqreturn_t lineevent_irq_handler(int irq, void *p) return IRQ_WAKE_THREAD; } +DEFINE_FREE(lineevent_free, struct lineevent_state *, if (!IS_ERR_OR_NULL(_T)) lineevent_free(_T)) + static int lineevent_create(struct gpio_device *gdev, void __user *ip) { struct gpioevent_request eventreq; - struct lineevent_state *le; + struct lineevent_state *le __free(lineevent_free) = NULL; struct gpio_desc *desc; - struct file *file; u32 offset; u32 lflags; u32 eflags; - int fd; int ret; int irq, irqflags = 0; char *label; @@ -2064,15 +2042,13 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) le->label = kstrndup(eventreq.consumer_label, sizeof(eventreq.consumer_label) - 1, GFP_KERNEL); - if (!le->label) { - ret = -ENOMEM; - goto out_free_le; - } + if (!le->label) + return -ENOMEM; } ret = gpiod_request_user(desc, le->label); if (ret) - goto out_free_le; + return ret; le->desc = desc; le->eflags = eflags; @@ -2080,15 +2056,13 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ret = gpiod_direction_input(desc); if (ret) - goto out_free_le; + return ret; gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); irq = gpiod_to_irq(desc); - if (irq <= 0) { - ret = -ENODEV; - goto out_free_le; - } + if (irq <= 0) + return -ENODEV; if (eflags & GPIOEVENT_REQUEST_RISING_EDGE) irqflags |= test_bit(GPIOD_FLAG_ACTIVE_LOW, &desc->flags) ? @@ -2105,13 +2079,11 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ret = blocking_notifier_chain_register(&gdev->device_notifier, &le->device_unregistered_nb); if (ret) - goto out_free_le; + return ret; label = make_irq_label(le->label); - if (IS_ERR(label)) { - ret = PTR_ERR(label); - goto out_free_le; - } + if (IS_ERR(label)) + return PTR_ERR(label); /* Request a thread to read the events */ ret = request_threaded_irq(irq, @@ -2122,46 +2094,25 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) le); if (ret) { free_irq_label(label); - goto out_free_le; + return ret; } le->irq = irq; - fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); - if (fd < 0) { - ret = fd; - goto out_free_le; - } - - file = anon_inode_getfile("gpio-event", - &lineevent_fileops, - le, - O_RDONLY | O_CLOEXEC); - if (IS_ERR(file)) { - ret = PTR_ERR(file); - goto out_put_unused_fd; - } + FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, + anon_inode_getfile("gpio-event", &lineevent_fileops, le, + O_RDONLY | O_CLOEXEC)); + if (fdf.err) + return fdf.err; + retain_and_null_ptr(le); - eventreq.fd = fd; - if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { - /* - * fput() will trigger the release() callback, so do not go onto - * the regular error cleanup path here. - */ - fput(file); - put_unused_fd(fd); + eventreq.fd = fd_prepare_fd(fdf); + if (copy_to_user(ip, &eventreq, sizeof(eventreq))) return -EFAULT; - } - fd_install(fd, file); + fd_publish(fdf); return 0; - -out_put_unused_fd: - put_unused_fd(fd); -out_free_le: - lineevent_free(le); - return ret; } static void gpio_v2_line_info_to_v1(struct gpio_v2_line_info *info_v2,