From patchwork Tue Apr 21 15:42:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 463359 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 1D8C114011D for ; Wed, 22 Apr 2015 01:43:49 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=gmail.com header.i=@gmail.com header.b=AHgv0Tyt; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932841AbbDUPn1 (ORCPT ); Tue, 21 Apr 2015 11:43:27 -0400 Received: from mail-lb0-f175.google.com ([209.85.217.175]:33165 "EHLO mail-lb0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932171AbbDUPnU (ORCPT ); Tue, 21 Apr 2015 11:43:20 -0400 Received: by lbbzk7 with SMTP id zk7so158984512lbb.0; Tue, 21 Apr 2015 08:43:18 -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=LntOB6vvaaBebKMLZsC6z8e0FzIR5hb2uyXdx02wnIE=; b=AHgv0Tytiq0wddpkvGyJK8U3AtXMFV+8K3IDbFXsfAC76OUDrHyBa+D0NUiG3B57HV bd3GBNmRgHHtwjw2/xB4WjBK67PHCPA9Dhiy4r/fimF8X4udEJOheQNTCOYMnkNX5l9J nsS8BpMPEaiBeRjz5M/6i0JAp918v8L7fp2MnDSLDvt3t85s4PkSeDE2vfaIB35VtdiZ bTWCqIAbArW5FW9uj5okDQoeakNQ6rwFNgvLWFkBVFafewqdEEVbcVCjQXndHadbkWe9 9Y/h+dt30jJ3r8YT7bFg+rN+3fcVXmPdjU/uC2KwJVnmtIzjz2uiLtj2VFVPGx2xjv8g xPSA== X-Received: by 10.112.125.193 with SMTP id ms1mr20919505lbb.31.1429630998370; Tue, 21 Apr 2015 08:43:18 -0700 (PDT) Received: from xi.terra (c193-14-96-226.cust.tele2.se. [193.14.96.226]) by mx.google.com with ESMTPSA id p7sm476067lae.47.2015.04.21.08.43.10 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Apr 2015 08:43:13 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.84) (envelope-from ) id 1YkaKN-00075N-B1; Tue, 21 Apr 2015 17:43:11 +0200 From: Johan Hovold To: Linus Walleij Cc: Alexandre Courbot , linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Johan Hovold Subject: [PATCH 20/23] gpio: sysfs: fix race between gpiod export and unexport Date: Tue, 21 Apr 2015 17:42:28 +0200 Message-Id: <1429630951-27082-21-git-send-email-johan@kernel.org> X-Mailer: git-send-email 2.0.5 In-Reply-To: <1429630951-27082-1-git-send-email-johan@kernel.org> References: <1429630951-27082-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 19c4351021d9..5eee3d0b3a81 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -659,9 +659,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__); @@ -670,33 +669,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);