aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Cernekee <kpc.mtd@gmail.com>2009-06-09 13:59:19 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-06-10 09:50:50 -0400
commitd9dd0887cc5c6df0dbbe5a307284610607eea7ab (patch)
tree1b6dc1bf5e90c6cd49896196abda9369a50ab3b2
parent6b5c94c6b4e1630a8e1ee7d30383d9396603749f (diff)
UBI: add reboot notifier
Terminate the UBI background thread prior to restarting the system. [Artem: amended comments a little] Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com> Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--drivers/mtd/ubi/build.c35
-rw-r--r--drivers/mtd/ubi/ubi.h4
2 files changed, 38 insertions, 1 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 964a99d48bc4..286ed594e5a0 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -41,6 +41,7 @@
41#include <linux/miscdevice.h> 41#include <linux/miscdevice.h>
42#include <linux/log2.h> 42#include <linux/log2.h>
43#include <linux/kthread.h> 43#include <linux/kthread.h>
44#include <linux/reboot.h>
44#include "ubi.h" 45#include "ubi.h"
45 46
46/* Maximum length of the 'mtd=' parameter */ 47/* Maximum length of the 'mtd=' parameter */
@@ -823,6 +824,34 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
823} 824}
824 825
825/** 826/**
827 * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot.
828 * @n: reboot notifier object
829 * @state: SYS_RESTART, SYS_HALT, or SYS_POWER_OFF
830 * @cmd: pointer to command string for RESTART2
831 *
832 * This function stops the UBI background thread so that the flash device
833 * remains quiescent when Linux restarts the system. Any queued work will be
834 * discarded, but this function will block until do_work() finishes if an
835 * operation is already in progress.
836 *
837 * This function solves a real-life problem observed on NOR flashes when an
838 * PEB erase operation starts, then the system is rebooted before the erase is
839 * finishes, and the boot loader gets confused and dies. So we prefer to finish
840 * the ongoing operation before rebooting.
841 */
842static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
843 void *cmd)
844{
845 struct ubi_device *ubi;
846
847 ubi = container_of(n, struct ubi_device, reboot_notifier);
848 if (ubi->bgt_thread)
849 kthread_stop(ubi->bgt_thread);
850 ubi_sync(ubi->ubi_num);
851 return NOTIFY_DONE;
852}
853
854/**
826 * ubi_attach_mtd_dev - attach an MTD device. 855 * ubi_attach_mtd_dev - attach an MTD device.
827 * @mtd: MTD device description object 856 * @mtd: MTD device description object
828 * @ubi_num: number to assign to the new UBI device 857 * @ubi_num: number to assign to the new UBI device
@@ -978,6 +1007,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
978 wake_up_process(ubi->bgt_thread); 1007 wake_up_process(ubi->bgt_thread);
979 spin_unlock(&ubi->wl_lock); 1008 spin_unlock(&ubi->wl_lock);
980 1009
1010 /* Flash device priority is 0 - UBI needs to shut down first */
1011 ubi->reboot_notifier.priority = 1;
1012 ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
1013 register_reboot_notifier(&ubi->reboot_notifier);
1014
981 ubi_devices[ubi_num] = ubi; 1015 ubi_devices[ubi_num] = ubi;
982 ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); 1016 ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
983 return ubi_num; 1017 return ubi_num;
@@ -1049,6 +1083,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
1049 * Before freeing anything, we have to stop the background thread to 1083 * Before freeing anything, we have to stop the background thread to
1050 * prevent it from doing anything on this device while we are freeing. 1084 * prevent it from doing anything on this device while we are freeing.
1051 */ 1085 */
1086 unregister_reboot_notifier(&ubi->reboot_notifier);
1052 if (ubi->bgt_thread) 1087 if (ubi->bgt_thread)
1053 kthread_stop(ubi->bgt_thread); 1088 kthread_stop(ubi->bgt_thread);
1054 1089
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 70ce48b95b64..28acd133c997 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -36,9 +36,9 @@
36#include <linux/device.h> 36#include <linux/device.h>
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/notifier.h>
39#include <linux/mtd/mtd.h> 40#include <linux/mtd/mtd.h>
40#include <linux/mtd/ubi.h> 41#include <linux/mtd/ubi.h>
41#include <linux/notifier.h>
42 42
43#include "ubi-media.h" 43#include "ubi-media.h"
44#include "scan.h" 44#include "scan.h"
@@ -348,6 +348,7 @@ struct ubi_wl_entry;
348 * @bgt_thread: background thread description object 348 * @bgt_thread: background thread description object
349 * @thread_enabled: if the background thread is enabled 349 * @thread_enabled: if the background thread is enabled
350 * @bgt_name: background thread name 350 * @bgt_name: background thread name
351 * @reboot_notifier: notifier to terminate background thread before rebooting
351 * 352 *
352 * @flash_size: underlying MTD device size (in bytes) 353 * @flash_size: underlying MTD device size (in bytes)
353 * @peb_count: count of physical eraseblocks on the MTD device 354 * @peb_count: count of physical eraseblocks on the MTD device
@@ -431,6 +432,7 @@ struct ubi_device {
431 struct task_struct *bgt_thread; 432 struct task_struct *bgt_thread;
432 int thread_enabled; 433 int thread_enabled;
433 char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; 434 char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
435 struct notifier_block reboot_notifier;
434 436
435 /* I/O sub-system's stuff */ 437 /* I/O sub-system's stuff */
436 long long flash_size; 438 long long flash_size;