From: Gu Zheng <guz.fnst@cn.fujitsu.com>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Tejun Heo <tj@kernel.org>, Toshi Kani <toshi.kani@hp.com>,
LKML <linux-kernel@vger.kernel.org>,
Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Subject: Re: [PATCH 1/2] driver core / ACPI: Avoid device hot remove locking issues
Date: Thu, 29 Aug 2013 10:02:22 +0800 [thread overview]
Message-ID: <521EABAE.8020801@cn.fujitsu.com> (raw)
In-Reply-To: <1454842.9oJVGeLlzB@vostro.rjw.lan>
On 08/28/2013 09:48 PM, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> device_hotplug_lock is held around the acpi_bus_trim() call in
> acpi_scan_hot_remove() which generally removes devices (it removes
> ACPI device objects at least, but it may also remove "physical"
> device objects through .detach() callbacks of ACPI scan handlers).
> Thus, potentially, device sysfs attributes are removed under that
> lock and to remove those attributes it is necessary to hold the
> s_active references of their directory entries for writing.
>
> On the other hand, the execution of a .show() or .store() callback
> from a sysfs attribute is carried out with that attribute's s_active
> reference held for reading. Consequently, if any device sysfs
> attribute that may be removed from within acpi_scan_hot_remove()
> through acpi_bus_trim() has a .store() or .show() callback which
> acquires device_hotplug_lock, the execution of that callback may
> deadlock with the removal of the attribute. [Unfortunately, the
> "online" device attribute of CPUs and memory blocks is one of them.]
>
> To avoid such deadlocks, make all of the sysfs attribute callbacks
> that need to lock device hotplug, for example store_online(), use
> a special function, lock_device_hotplug_sysfs(), to lock device
> hotplug and return the result of that function immediately if it is
> not zero. This will cause the s_active reference of the directory
> entry in question to be released and the syscall to be restarted
> if device_hotplug_lock cannot be acquired.
>
> [show_online() actually doesn't need to lock device hotplug, but
> it is useful to serialize it with respect to device_offline() and
> device_online() for the same device (in case user space attempts to
> run them concurrently) which can be done with the help of
> device_lock().]
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Reported-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> Reported-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
Tested-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
> ---
> drivers/acpi/sysfs.c | 5 ++++-
> drivers/base/core.c | 43 ++++++++++++++++++++++++++++---------------
> drivers/base/memory.c | 4 +++-
> include/linux/device.h | 1 +
> 4 files changed, 36 insertions(+), 17 deletions(-)
>
> Index: linux-pm/drivers/base/core.c
> ===================================================================
> --- linux-pm.orig/drivers/base/core.c
> +++ linux-pm/drivers/base/core.c
> @@ -49,6 +49,28 @@ static struct kobject *dev_kobj;
> struct kobject *sysfs_dev_char_kobj;
> struct kobject *sysfs_dev_block_kobj;
>
> +static DEFINE_MUTEX(device_hotplug_lock);
> +
> +void lock_device_hotplug(void)
> +{
> + mutex_lock(&device_hotplug_lock);
> +}
> +
> +void unlock_device_hotplug(void)
> +{
> + mutex_unlock(&device_hotplug_lock);
> +}
> +
> +int lock_device_hotplug_sysfs(void)
> +{
> + if (mutex_trylock(&device_hotplug_lock))
> + return 0;
> +
> + /* Avoid busy looping (5 ms of sleep should do). */
> + msleep(5);
> + return restart_syscall();
> +}
> +
> #ifdef CONFIG_BLOCK
> static inline int device_is_not_partition(struct device *dev)
> {
> @@ -408,9 +430,9 @@ static ssize_t show_online(struct device
> {
> bool val;
>
> - lock_device_hotplug();
> + device_lock(dev);
> val = !dev->offline;
> - unlock_device_hotplug();
> + device_unlock(dev);
> return sprintf(buf, "%u\n", val);
> }
>
> @@ -424,7 +446,10 @@ static ssize_t store_online(struct devic
> if (ret < 0)
> return ret;
>
> - lock_device_hotplug();
> + ret = lock_device_hotplug_sysfs();
> + if (ret)
> + return ret;
> +
> ret = val ? device_online(dev) : device_offline(dev);
> unlock_device_hotplug();
> return ret < 0 ? ret : count;
> @@ -1479,18 +1504,6 @@ EXPORT_SYMBOL_GPL(put_device);
> EXPORT_SYMBOL_GPL(device_create_file);
> EXPORT_SYMBOL_GPL(device_remove_file);
>
> -static DEFINE_MUTEX(device_hotplug_lock);
> -
> -void lock_device_hotplug(void)
> -{
> - mutex_lock(&device_hotplug_lock);
> -}
> -
> -void unlock_device_hotplug(void)
> -{
> - mutex_unlock(&device_hotplug_lock);
> -}
> -
> static int device_check_offline(struct device *dev, void *not_used)
> {
> int ret;
> Index: linux-pm/drivers/base/memory.c
> ===================================================================
> --- linux-pm.orig/drivers/base/memory.c
> +++ linux-pm/drivers/base/memory.c
> @@ -351,7 +351,9 @@ store_mem_state(struct device *dev,
>
> mem = container_of(dev, struct memory_block, dev);
>
> - lock_device_hotplug();
> + ret = lock_device_hotplug_sysfs();
> + if (ret)
> + return ret;
>
> if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) {
> offline = false;
> Index: linux-pm/drivers/acpi/sysfs.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/sysfs.c
> +++ linux-pm/drivers/acpi/sysfs.c
> @@ -796,7 +796,10 @@ static ssize_t force_remove_store(struct
> if (ret < 0)
> return ret;
>
> - lock_device_hotplug();
> + ret = lock_device_hotplug_sysfs();
> + if (ret)
> + return ret;
> +
> acpi_force_hot_remove = val;
> unlock_device_hotplug();
> return size;
> Index: linux-pm/include/linux/device.h
> ===================================================================
> --- linux-pm.orig/include/linux/device.h
> +++ linux-pm/include/linux/device.h
> @@ -895,6 +895,7 @@ static inline bool device_supports_offli
>
> extern void lock_device_hotplug(void);
> extern void unlock_device_hotplug(void);
> +extern int lock_device_hotplug_sysfs(void);
> extern int device_offline(struct device *dev);
> extern int device_online(struct device *dev);
> /*
>
>
next prev parent reply other threads:[~2013-08-29 2:06 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-25 20:09 [PATCH] driver core / ACPI: Avoid device removal locking problems Rafael J. Wysocki
2013-08-25 21:54 ` Greg Kroah-Hartman
2013-08-26 3:13 ` Gu Zheng
2013-08-26 12:42 ` Rafael J. Wysocki
2013-08-26 14:43 ` Rafael J. Wysocki
2013-08-26 15:02 ` Rafael J. Wysocki
2013-08-27 3:26 ` Gu Zheng
2013-08-27 9:21 ` Gu Zheng
2013-08-27 18:36 ` Tejun Heo
2013-08-27 21:45 ` Rafael J. Wysocki
2013-08-28 10:03 ` Gu Zheng
2013-08-28 12:24 ` Tejun Heo
2013-08-28 13:24 ` Rafael J. Wysocki
2013-08-28 13:45 ` [PATCH 0/2] " Rafael J. Wysocki
2013-08-28 13:48 ` [PATCH 1/2] driver core / ACPI: Avoid device hot remove locking issues Rafael J. Wysocki
2013-08-28 18:53 ` Greg Kroah-Hartman
2013-08-29 2:02 ` Gu Zheng [this message]
2013-08-28 13:51 ` [PATCH 2/2] ACPI / hotplug: Remove containers synchronously Rafael J. Wysocki
2013-08-28 18:53 ` Greg Kroah-Hartman
2013-08-29 2:02 ` Gu Zheng
2013-08-28 17:06 ` [PATCH 0/2] driver core / ACPI: Avoid device removal locking problems Toshi Kani
2013-08-29 2:00 ` Gu Zheng
2013-08-27 21:38 ` [PATCH] " Toshi Kani
2013-08-28 2:12 ` Gu Zheng
2013-08-28 16:55 ` Toshi Kani
2013-08-27 2:03 ` Gu Zheng
2013-08-27 2:38 ` Gu Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=521EABAE.8020801@cn.fujitsu.com \
--to=guz.fnst@cn.fujitsu.com \
--cc=gregkh@linuxfoundation.org \
--cc=isimatu.yasuaki@jp.fujitsu.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=tj@kernel.org \
--cc=toshi.kani@hp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.