summaryrefslogtreecommitdiffstats
path: root/security/keys/gc.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-09-24 10:35:18 +0100
committerDavid Howells <dhowells@redhat.com>2013-09-24 10:35:18 +0100
commitb2a4df200d570b2c33a57e1ebfa5896e4bc81b69 (patch)
tree7fa48ae3c5ecff90d6d1f662fd91af5ddf74d56d /security/keys/gc.c
parent3cb989501c2688cacbb7dc4b0d353faf838f53a1 (diff)
downloadlinux-b2a4df200d570b2c33a57e1ebfa5896e4bc81b69.tar.bz2
KEYS: Expand the capacity of a keyring
Expand the capacity of a keyring to be able to hold a lot more keys by using the previously added associative array implementation. Currently the maximum capacity is: (PAGE_SIZE - sizeof(header)) / sizeof(struct key *) which, on a 64-bit system, is a little more 500. However, since this is being used for the NFS uid mapper, we need more than that. The new implementation gives us effectively unlimited capacity. With some alterations, the keyutils testsuite runs successfully to completion after this patch is applied. The alterations are because (a) keyrings that are simply added to no longer appear ordered and (b) some of the errors have changed a bit. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security/keys/gc.c')
-rw-r--r--security/keys/gc.c33
1 files changed, 14 insertions, 19 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index d67c97bb1025..cce621c33dce 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -130,6 +130,13 @@ void key_gc_keytype(struct key_type *ktype)
kleave("");
}
+static int key_gc_keyring_func(const void *object, void *iterator_data)
+{
+ const struct key *key = object;
+ time_t *limit = iterator_data;
+ return key_is_dead(key, *limit);
+}
+
/*
* Garbage collect pointers from a keyring.
*
@@ -138,10 +145,9 @@ void key_gc_keytype(struct key_type *ktype)
*/
static void key_gc_keyring(struct key *keyring, time_t limit)
{
- struct keyring_list *klist;
- int loop;
+ int result;
- kenter("%x", key_serial(keyring));
+ kenter("%x{%s}", keyring->serial, keyring->description ?: "");
if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED)))
@@ -149,27 +155,17 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
/* scan the keyring looking for dead keys */
rcu_read_lock();
- klist = rcu_dereference(keyring->payload.subscriptions);
- if (!klist)
- goto unlock_dont_gc;
-
- loop = klist->nkeys;
- smp_rmb();
- for (loop--; loop >= 0; loop--) {
- struct key *key = rcu_dereference(klist->keys[loop]);
- if (key_is_dead(key, limit))
- goto do_gc;
- }
-
-unlock_dont_gc:
+ result = assoc_array_iterate(&keyring->keys,
+ key_gc_keyring_func, &limit);
rcu_read_unlock();
+ if (result == true)
+ goto do_gc;
+
dont_gc:
kleave(" [no gc]");
return;
do_gc:
- rcu_read_unlock();
-
keyring_gc(keyring, limit);
kleave(" [gc]");
}
@@ -392,7 +388,6 @@ found_unreferenced_key:
*/
found_keyring:
spin_unlock(&key_serial_lock);
- kdebug("scan keyring %d", key->serial);
key_gc_keyring(key, limit);
goto maybe_resched;