| From a66270ca9ed46b11451cf61661d042e915d0bcb3 Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Wed, 8 Jul 2020 12:25:20 -0400 |
| Subject: [PATCH] dm: use noio when sending kobject event |
| |
| commit 6958c1c640af8c3f40fa8a2eee3b5b905d95b677 upstream. |
| |
| kobject_uevent may allocate memory and it may be called while there are dm |
| devices suspended. The allocation may recurse into a suspended device, |
| causing a deadlock. We must set the noio flag when sending a uevent. |
| |
| The observed deadlock was reported here: |
| https://www.redhat.com/archives/dm-devel/2020-March/msg00025.html |
| |
| Reported-by: Khazhismel Kumykov <khazhy@google.com> |
| Reported-by: Tahsin Erdogan <tahsin@google.com> |
| Reported-by: Gabriel Krisman Bertazi <krisman@collabora.com> |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/md/dm.c b/drivers/md/dm.c |
| index d6a08750a61f..1034e1f410bc 100644 |
| --- a/drivers/md/dm.c |
| +++ b/drivers/md/dm.c |
| @@ -12,6 +12,7 @@ |
| #include <linux/init.h> |
| #include <linux/module.h> |
| #include <linux/mutex.h> |
| +#include <linux/sched/mm.h> |
| #include <linux/sched/signal.h> |
| #include <linux/blkpg.h> |
| #include <linux/bio.h> |
| @@ -2887,17 +2888,25 @@ EXPORT_SYMBOL_GPL(dm_internal_resume_fast); |
| int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, |
| unsigned cookie) |
| { |
| + int r; |
| + unsigned noio_flag; |
| char udev_cookie[DM_COOKIE_LENGTH]; |
| char *envp[] = { udev_cookie, NULL }; |
| |
| + noio_flag = memalloc_noio_save(); |
| + |
| if (!cookie) |
| - return kobject_uevent(&disk_to_dev(md->disk)->kobj, action); |
| + r = kobject_uevent(&disk_to_dev(md->disk)->kobj, action); |
| else { |
| snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u", |
| DM_COOKIE_ENV_VAR_NAME, cookie); |
| - return kobject_uevent_env(&disk_to_dev(md->disk)->kobj, |
| - action, envp); |
| + r = kobject_uevent_env(&disk_to_dev(md->disk)->kobj, |
| + action, envp); |
| } |
| + |
| + memalloc_noio_restore(noio_flag); |
| + |
| + return r; |
| } |
| |
| uint32_t dm_next_uevent_seq(struct mapped_device *md) |
| -- |
| 2.27.0 |
| |