From: Kevin Cernekee <kpc.mtd@gmail.com>
To: <dedekind@infradead.org>, <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH] MTD: Add UBI reboot notifier
Date: Mon, 8 Jun 2009 22:14:12 -0700 [thread overview]
Message-ID: <018abcd2d98090bda0f75d3c95c9ec85@localhost> (raw)
ubifs_sync_fs() may queue up a new UBI erase transaction, which is
processed in the background:
bash# sync
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubi_sync: enter
ubi_sync: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
bash# cfi_amdstd_erase_varsize: exit
Normally this is not a big deal. However, during the final sync before
rebooting, it initiates an erase operation that is potentially still
active when Linux restarts the machine:
bash# reboot -f
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubi_sync: enter
ubi_sync: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
Restarting system.
<Flash is stuck in FL_ERASE mode - system hangs>
This is easiest to observe on a NOR flash. One factor is the long erase
time. The other reason is because getting a NOR flash stuck in FL_ERASE
mode will prevent the bootloader from running, unless the board provides
a way for the processor to automatically reset the flash. In my
experience, many boards do not.
My proposal is to add a reboot notifier to let the UBI background thread
terminate gracefully. The new ordering looks like this:
bash# reboot -f
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
ubi_reboot_notifier: enter
cfi_amdstd_erase_varsize: exit
ubi_reboot_notifier: exit
cfi_amdstd_reboot: enter
cfi_amdstd_reboot: exit
cfi_amdstd_reboot doesn't really exist, but I added a dummy notifier to
make sure that the ordering would be correct when using drivers that do
have this feature.
Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com>
---
drivers/mtd/ubi/build.c | 24 ++++++++++++++++++++++++
drivers/mtd/ubi/ubi.h | 2 ++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 4048db8..ca88059 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -41,6 +41,7 @@
#include <linux/miscdevice.h>
#include <linux/log2.h>
#include <linux/kthread.h>
+#include <linux/reboot.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
@@ -726,6 +727,23 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
}
/**
+ * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot
+ * @n: notifier_block struct (inside our struct ubi_device)
+ * @val: unused
+ * @v: unused
+ */
+static int ubi_reboot_notifier(struct notifier_block *n, unsigned long val,
+ void *v)
+{
+ struct ubi_device *ubi = container_of(n, struct ubi_device,
+ reboot_notifier);
+
+ if (ubi->bgt_thread)
+ kthread_stop(ubi->bgt_thread);
+ return NOTIFY_DONE;
+}
+
+/**
* ubi_attach_mtd_dev - attach an MTD device.
* @mtd: MTD device description object
* @ubi_num: number to assign to the new UBI device
@@ -876,6 +894,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi->thread_enabled = 1;
wake_up_process(ubi->bgt_thread);
+ /* Flash device priority is 0. UBI needs to shut down first. */
+ ubi->reboot_notifier.priority = 1;
+ ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
+ register_reboot_notifier(&ubi->reboot_notifier);
+
ubi_devices[ubi_num] = ubi;
return ubi_num;
@@ -945,6 +968,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
* Before freeing anything, we have to stop the background thread to
* prevent it from doing anything on this device while we are freeing.
*/
+ unregister_reboot_notifier(&ubi->reboot_notifier);
if (ubi->bgt_thread)
kthread_stop(ubi->bgt_thread);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c055511..44a45b9 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -36,6 +36,7 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include <linux/notifier.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/ubi.h>
@@ -420,6 +421,7 @@ struct ubi_device {
struct task_struct *bgt_thread;
int thread_enabled;
char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
+ struct notifier_block reboot_notifier;
/* I/O sub-system's stuff */
long long flash_size;
--
1.6.3.1
WARNING: multiple messages have this Message-ID (diff)
From: Kevin Cernekee <kpc.mtd@gmail.com>
To: <dedekind@infradead.org>, <dwmw2@infradead.org>
Cc: <linux-mtd@lists.infradead.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH] MTD: Add UBI reboot notifier
Date: Mon, 8 Jun 2009 22:14:12 -0700 [thread overview]
Message-ID: <018abcd2d98090bda0f75d3c95c9ec85@localhost> (raw)
ubifs_sync_fs() may queue up a new UBI erase transaction, which is
processed in the background:
bash# sync
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubi_sync: enter
ubi_sync: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
bash# cfi_amdstd_erase_varsize: exit
Normally this is not a big deal. However, during the final sync before
rebooting, it initiates an erase operation that is potentially still
active when Linux restarts the machine:
bash# reboot -f
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubi_sync: enter
ubi_sync: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
Restarting system.
<Flash is stuck in FL_ERASE mode - system hangs>
This is easiest to observe on a NOR flash. One factor is the long erase
time. The other reason is because getting a NOR flash stuck in FL_ERASE
mode will prevent the bootloader from running, unless the board provides
a way for the processor to automatically reset the flash. In my
experience, many boards do not.
My proposal is to add a reboot notifier to let the UBI background thread
terminate gracefully. The new ordering looks like this:
bash# reboot -f
ubifs_sync_fs: enter
schedule_erase: enter
schedule_erase: exit
ubifs_sync_fs: exit
cfi_amdstd_erase_varsize: enter
ubi_reboot_notifier: enter
cfi_amdstd_erase_varsize: exit
ubi_reboot_notifier: exit
cfi_amdstd_reboot: enter
cfi_amdstd_reboot: exit
cfi_amdstd_reboot doesn't really exist, but I added a dummy notifier to
make sure that the ordering would be correct when using drivers that do
have this feature.
Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com>
---
drivers/mtd/ubi/build.c | 24 ++++++++++++++++++++++++
drivers/mtd/ubi/ubi.h | 2 ++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 4048db8..ca88059 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -41,6 +41,7 @@
#include <linux/miscdevice.h>
#include <linux/log2.h>
#include <linux/kthread.h>
+#include <linux/reboot.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
@@ -726,6 +727,23 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
}
/**
+ * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot
+ * @n: notifier_block struct (inside our struct ubi_device)
+ * @val: unused
+ * @v: unused
+ */
+static int ubi_reboot_notifier(struct notifier_block *n, unsigned long val,
+ void *v)
+{
+ struct ubi_device *ubi = container_of(n, struct ubi_device,
+ reboot_notifier);
+
+ if (ubi->bgt_thread)
+ kthread_stop(ubi->bgt_thread);
+ return NOTIFY_DONE;
+}
+
+/**
* ubi_attach_mtd_dev - attach an MTD device.
* @mtd: MTD device description object
* @ubi_num: number to assign to the new UBI device
@@ -876,6 +894,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi->thread_enabled = 1;
wake_up_process(ubi->bgt_thread);
+ /* Flash device priority is 0. UBI needs to shut down first. */
+ ubi->reboot_notifier.priority = 1;
+ ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
+ register_reboot_notifier(&ubi->reboot_notifier);
+
ubi_devices[ubi_num] = ubi;
return ubi_num;
@@ -945,6 +968,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
* Before freeing anything, we have to stop the background thread to
* prevent it from doing anything on this device while we are freeing.
*/
+ unregister_reboot_notifier(&ubi->reboot_notifier);
if (ubi->bgt_thread)
kthread_stop(ubi->bgt_thread);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c055511..44a45b9 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -36,6 +36,7 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include <linux/notifier.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/ubi.h>
@@ -420,6 +421,7 @@ struct ubi_device {
struct task_struct *bgt_thread;
int thread_enabled;
char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
+ struct notifier_block reboot_notifier;
/* I/O sub-system's stuff */
long long flash_size;
--
1.6.3.1
next reply other threads:[~2009-06-09 5:47 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-09 5:14 Kevin Cernekee [this message]
2009-06-09 5:14 ` [PATCH] MTD: Add UBI reboot notifier Kevin Cernekee
2009-06-09 12:13 ` Artem Bityutskiy
2009-06-09 12:13 ` Artem Bityutskiy
2009-06-09 12:32 ` Artem Bityutskiy
2009-06-09 12:32 ` Artem Bityutskiy
2009-06-09 17:59 ` [PATCHv2] " Kevin Cernekee
2009-06-09 17:59 ` Kevin Cernekee
2009-06-10 9:35 ` Artem Bityutskiy
2009-06-10 9:35 ` Artem Bityutskiy
2009-06-10 11:59 ` Artem Bityutskiy
2009-06-10 11:59 ` Artem Bityutskiy
2009-06-10 17:27 ` Kevin Cernekee
2009-06-10 17:27 ` Kevin Cernekee
2010-02-12 13:13 ` Artem Bityutskiy
2010-02-12 13:13 ` Artem Bityutskiy
2010-02-12 13:45 ` Norbert van Bolhuis
2010-02-12 13:45 ` Norbert van Bolhuis
2010-02-12 15:20 ` David Woodhouse
2010-02-12 15:20 ` David Woodhouse
2010-02-12 15:21 ` Artem Bityutskiy
2010-02-12 15:21 ` Artem Bityutskiy
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=018abcd2d98090bda0f75d3c95c9ec85@localhost \
--to=kpc.mtd@gmail.com \
--cc=dedekind@infradead.org \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
/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.