Crash: add lock to serialize crash hotplug handling
[linux-block.git] / kernel / crash_core.c
index 03a7932cde0a518939f8325fb450c91391b08891..2f675ef045d40db9704ad940663847db42bdf196 100644 (file)
@@ -739,6 +739,17 @@ subsys_initcall(crash_notes_memory_init);
 #undef pr_fmt
 #define pr_fmt(fmt) "crash hp: " fmt
 
+/*
+ * Different than kexec/kdump loading/unloading/jumping/shrinking which
+ * usually rarely happen, there will be many crash hotplug events notified
+ * during one short period, e.g one memory board is hot added and memory
+ * regions are online. So mutex lock  __crash_hotplug_lock is used to
+ * serialize the crash hotplug handling specifically.
+ */
+DEFINE_MUTEX(__crash_hotplug_lock);
+#define crash_hotplug_lock() mutex_lock(&__crash_hotplug_lock)
+#define crash_hotplug_unlock() mutex_unlock(&__crash_hotplug_lock)
+
 /*
  * This routine utilized when the crash_hotplug sysfs node is read.
  * It reflects the kernel's ability/permission to update the crash
@@ -748,9 +759,11 @@ int crash_check_update_elfcorehdr(void)
 {
        int rc = 0;
 
+       crash_hotplug_lock();
        /* Obtain lock while reading crash information */
        if (!kexec_trylock()) {
                pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
+               crash_hotplug_unlock();
                return 0;
        }
        if (kexec_crash_image) {
@@ -761,6 +774,7 @@ int crash_check_update_elfcorehdr(void)
        }
        /* Release lock now that update complete */
        kexec_unlock();
+       crash_hotplug_unlock();
 
        return rc;
 }
@@ -783,9 +797,11 @@ static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu)
 {
        struct kimage *image;
 
+       crash_hotplug_lock();
        /* Obtain lock while changing crash information */
        if (!kexec_trylock()) {
                pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n");
+               crash_hotplug_unlock();
                return;
        }
 
@@ -852,6 +868,7 @@ static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu)
 out:
        /* Release lock now that update complete */
        kexec_unlock();
+       crash_hotplug_unlock();
 }
 
 static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *v)