From patchwork Mon May 4 15:10:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 467662 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id DB81B1402AB for ; Tue, 5 May 2015 01:17:55 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=jcC7gmHd; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752391AbbEDPRO (ORCPT ); Mon, 4 May 2015 11:17:14 -0400 Received: from mail-lb0-f169.google.com ([209.85.217.169]:35437 "EHLO mail-lb0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752071AbbEDPNr (ORCPT ); Mon, 4 May 2015 11:13:47 -0400 Received: by lbbuc2 with SMTP id uc2so107027548lbb.2; Mon, 04 May 2015 08:13:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=0gvS/HgvSs+hRMIDuBa+UZ2Xh9lGTQmKtS2MCNmBuFs=; b=jcC7gmHdNf32L+Jr+SVMNxw3KHFH1PIgQUOXUgaLz2GxfFgeJc9OOt3CQlg+JKEhSF kVe7/yjEjYXwN58LjKsSAAqfghjFudg2ND2c3fXJQlud5TaV+ZYLQzrSVEjHNqq18HUZ u7yTmLCD33QCFwCzHpcG3xXefDf+eilM8aDRKeTdK3WSTfMUAv0VvRDDefGiSHTM5OA1 m2fHWEm5QLZCAXRWJTeLRZKc7jR+8H63dR8fuyOLc8ep2qrJfYVEWkB39Q6821gqbS4g Jvhi7xV0uQitqnWmwrCxO8l4SSbHxoKP8o4JAHaervXnaCZzELYmQwp43P1/n/U+Tk0B 5RLQ== X-Received: by 10.112.200.230 with SMTP id jv6mr20011963lbc.21.1430752425778; Mon, 04 May 2015 08:13:45 -0700 (PDT) Received: from xi.terra (c193-14-96-226.cust.tele2.se. [193.14.96.226]) by mx.google.com with ESMTPSA id xx2sm3413968lbb.13.2015.05.04.08.13.41 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 May 2015 08:13:44 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.84) (envelope-from ) id 1YpI3z-00043H-LZ; Mon, 04 May 2015 17:13:43 +0200 From: Johan Hovold To: Linus Walleij Cc: Alexandre Courbot , linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Johan Hovold Subject: [PATCH v2 20/23] gpio: sysfs: fix race between gpiod export and unexport Date: Mon, 4 May 2015 17:10:45 +0200 Message-Id: <1430752248-15401-21-git-send-email-johan@kernel.org> X-Mailer: git-send-email 2.0.5 In-Reply-To: <1430752248-15401-1-git-send-email-johan@kernel.org> References: <1430752248-15401-1-git-send-email-johan@kernel.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Make sure to deregister the class device (and release the irq) while holding the sysfs lock in gpio_unexport to prevent racing with gpio_export. Note that this requires the recently introduced per-gpio locking to avoid a deadlock with the kernfs active protection when waiting for the attribute operations to drain during deregistration. Signed-off-by: Johan Hovold --- drivers/gpio/gpiolib-sysfs.c | 51 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 1bb05aa33a84..1540f7d60f06 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -674,9 +674,8 @@ EXPORT_SYMBOL_GPL(gpiod_export_link); */ void gpiod_unexport(struct gpio_desc *desc) { - struct gpiod_data *data; - int status = 0; - struct device *dev = NULL; + struct gpiod_data *data; + struct device *dev; if (!desc) { pr_warn("%s: invalid GPIO\n", __func__); @@ -685,33 +684,35 @@ void gpiod_unexport(struct gpio_desc *desc) mutex_lock(&sysfs_lock); - if (test_bit(FLAG_EXPORT, &desc->flags)) { + if (!test_bit(FLAG_EXPORT, &desc->flags)) + goto err_unlock; - dev = class_find_device(&gpio_class, NULL, desc, match_export); - if (dev) { - clear_bit(FLAG_SYSFS_DIR, &desc->flags); - clear_bit(FLAG_EXPORT, &desc->flags); - } else - status = -ENODEV; - } + dev = class_find_device(&gpio_class, NULL, desc, match_export); + if (!dev) + goto err_unlock; + + data = dev_get_drvdata(dev); + + clear_bit(FLAG_SYSFS_DIR, &desc->flags); + clear_bit(FLAG_EXPORT, &desc->flags); + + device_unregister(dev); + + /* + * Release irq after deregistration to prevent race with edge_store. + */ + if (desc->flags & GPIO_TRIGGER_MASK) + gpio_sysfs_free_irq(dev); mutex_unlock(&sysfs_lock); - if (dev) { - data = dev_get_drvdata(dev); - device_unregister(dev); - /* - * Release irq after deregistration to prevent race with - * edge_store. - */ - if (desc->flags & GPIO_TRIGGER_MASK) - gpio_sysfs_free_irq(dev); - put_device(dev); - kfree(data); - } + put_device(dev); + kfree(data); - if (status) - gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return; + +err_unlock: + mutex_unlock(&sysfs_lock); } EXPORT_SYMBOL_GPL(gpiod_unexport);