diff options
author | Sylvain Chouleur <sylvain.chouleur@intel.com> | 2016-07-15 15:36:30 -0400 |
---|---|---|
committer | Matt Fleming <matt@codeblueprint.co.uk> | 2016-09-09 11:08:42 -0400 |
commit | 21b3ddd39feecd2f4d6c52bcd30f0a4fa14f125a (patch) | |
tree | 40773635e6415ce23293c67eda0327dddec90ae7 /fs/efivarfs | |
parent | 217b27d4671a0a3f34147f1b341683d36b7457db (diff) |
efi: Don't use spinlocks for efi vars
All efivars operations are protected by a spinlock which prevents
interruptions and preemption. This is too restricted, we just need a
lock preventing concurrency.
The idea is to use a semaphore of count 1 and to have two ways of
locking, depending on the context:
- In interrupt context, we call down_trylock(), if it fails we return
an error
- In normal context, we call down_interruptible()
We don't use a mutex here because the mutex_trylock() function must not
be called from interrupt context, whereas the down_trylock() can.
Signed-off-by: Sylvain Chouleur <sylvain.chouleur@intel.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Sylvain Chouleur <sylvain.chouleur@gmail.com>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Diffstat (limited to 'fs/efivarfs')
-rw-r--r-- | fs/efivarfs/inode.c | 5 | ||||
-rw-r--r-- | fs/efivarfs/super.c | 9 |
2 files changed, 11 insertions, 3 deletions
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 1d73fc6dba13..cbb50cadcffc 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c | |||
@@ -105,7 +105,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, | |||
105 | 105 | ||
106 | inode->i_private = var; | 106 | inode->i_private = var; |
107 | 107 | ||
108 | efivar_entry_add(var, &efivarfs_list); | 108 | err = efivar_entry_add(var, &efivarfs_list); |
109 | if (err) | ||
110 | goto out; | ||
111 | |||
109 | d_instantiate(dentry, inode); | 112 | d_instantiate(dentry, inode); |
110 | dget(dentry); | 113 | dget(dentry); |
111 | out: | 114 | out: |
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index 688ccc16b702..01e3d6e53944 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c | |||
@@ -161,7 +161,9 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, | |||
161 | kfree(name); | 161 | kfree(name); |
162 | 162 | ||
163 | efivar_entry_size(entry, &size); | 163 | efivar_entry_size(entry, &size); |
164 | efivar_entry_add(entry, &efivarfs_list); | 164 | err = efivar_entry_add(entry, &efivarfs_list); |
165 | if (err) | ||
166 | goto fail_inode; | ||
165 | 167 | ||
166 | inode_lock(inode); | 168 | inode_lock(inode); |
167 | inode->i_private = entry; | 169 | inode->i_private = entry; |
@@ -182,7 +184,10 @@ fail: | |||
182 | 184 | ||
183 | static int efivarfs_destroy(struct efivar_entry *entry, void *data) | 185 | static int efivarfs_destroy(struct efivar_entry *entry, void *data) |
184 | { | 186 | { |
185 | efivar_entry_remove(entry); | 187 | int err = efivar_entry_remove(entry); |
188 | |||
189 | if (err) | ||
190 | return err; | ||
186 | kfree(entry); | 191 | kfree(entry); |
187 | return 0; | 192 | return 0; |
188 | } | 193 | } |