efi: pstore: move workqueue handling out of efivars
authorArd Biesheuvel <ardb@kernel.org>
Wed, 23 Sep 2020 08:07:49 +0000 (10:07 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Tue, 29 Sep 2020 17:40:57 +0000 (19:40 +0200)
The worker thread that gets kicked off to sync the state of the
EFI variable list is only used by the EFI pstore implementation,
and is defined in its source file. So let's move its scheduling
there as well. Since our efivar_init() scan will bail on duplicate
entries, there is no need to disable the workqueue like we did
before, so we can run it unconditionally.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/vars.c
include/linux/efi.h

index 785f5e6b3a411f617abe66a690a93b88d6cf685d..0ef086e43090bb14f3789466bedf0af049e3d18d 100644 (file)
@@ -21,6 +21,7 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
         EFI_VARIABLE_RUNTIME_ACCESS)
 
 static LIST_HEAD(efi_pstore_list);
+static DECLARE_WORK(efivar_work, NULL);
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
@@ -267,8 +268,9 @@ static int efi_pstore_write(struct pstore_record *record)
        ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
                              preemptible(), record->size, record->psi->buf);
 
-       if (record->reason == KMSG_DUMP_OOPS)
-               efivar_run_worker();
+       if (record->reason == KMSG_DUMP_OOPS && try_module_get(THIS_MODULE))
+               if (!schedule_work(&efivar_work))
+                       module_put(THIS_MODULE);
 
        return ret;
 };
@@ -412,6 +414,7 @@ static void efi_pstore_update_entries(struct work_struct *work)
        }
 
        kfree(entry);
+       module_put(THIS_MODULE);
 }
 
 static __init int efivars_pstore_init(void)
index 973eef234b365e530576fe09cc407cbb6e0d1366..ffb12f6efc97bc6abc603a3b4f8eaa453c1c9d58 100644 (file)
@@ -32,10 +32,6 @@ static struct efivars *__efivars;
  */
 static DEFINE_SEMAPHORE(efivars_lock);
 
-static bool efivar_wq_enabled = true;
-DECLARE_WORK(efivar_work, NULL);
-EXPORT_SYMBOL_GPL(efivar_work);
-
 static bool
 validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
                     unsigned long len)
@@ -391,13 +387,6 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
        size_t i, len8 = len16 / sizeof(efi_char16_t);
        char *str8;
 
-       /*
-        * Disable the workqueue since the algorithm it uses for
-        * detecting new variables won't work with this buggy
-        * implementation of GetNextVariableName().
-        */
-       efivar_wq_enabled = false;
-
        str8 = kzalloc(len8, GFP_KERNEL);
        if (!str8)
                return;
@@ -1157,16 +1146,6 @@ struct kobject *efivars_kobject(void)
 }
 EXPORT_SYMBOL_GPL(efivars_kobject);
 
-/**
- * efivar_run_worker - schedule the efivar worker thread
- */
-void efivar_run_worker(void)
-{
-       if (efivar_wq_enabled)
-               schedule_work(&efivar_work);
-}
-EXPORT_SYMBOL_GPL(efivar_run_worker);
-
 /**
  * efivars_register - register an efivars
  * @efivars: efivars to register
index 7066c11ab82f4f085c2f14c7452faec44a76a608..ab8c8033121784dc1fa1ebc268744d39f677e6fd 100644 (file)
@@ -1037,9 +1037,6 @@ bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
 bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
                                  size_t len);
 
-extern struct work_struct efivar_work;
-void efivar_run_worker(void);
-
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);