|
|
6d55b5 |
From 779a298a583d64cb9a200cc35a4def3a120e03f7 Mon Sep 17 00:00:00 2001
|
|
|
6d55b5 |
From: Greg Hudson <ghudson@mit.edu>
|
|
|
6d55b5 |
Date: Sat, 4 Aug 2018 23:55:18 -0400
|
|
|
6d55b5 |
Subject: [PATCH] Use a hash table for MEMORY ccache resolution
|
|
|
6d55b5 |
|
|
|
6d55b5 |
In cc_memory.c, replace the linked list of caches with a hash table,
|
|
|
6d55b5 |
for better performance with large numbers of memory caches.
|
|
|
6d55b5 |
|
|
|
6d55b5 |
ticket: 8722 (new)
|
|
|
6d55b5 |
(cherry picked from commit 088ba228acce4fd55bbb7c30122fe2703b8beeb8)
|
|
|
6d55b5 |
---
|
|
|
6d55b5 |
src/lib/krb5/ccache/cc_memory.c | 77 +++++++++++++++------------------
|
|
|
6d55b5 |
1 file changed, 34 insertions(+), 43 deletions(-)
|
|
|
6d55b5 |
|
|
|
6d55b5 |
diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
|
|
|
6d55b5 |
index cfd5c6389..114ef6913 100644
|
|
|
6d55b5 |
--- a/src/lib/krb5/ccache/cc_memory.c
|
|
|
6d55b5 |
+++ b/src/lib/krb5/ccache/cc_memory.c
|
|
|
6d55b5 |
@@ -26,6 +26,7 @@
|
|
|
6d55b5 |
|
|
|
6d55b5 |
#include "cc-int.h"
|
|
|
6d55b5 |
#include "../krb/int-proto.h"
|
|
|
6d55b5 |
+#include "k5-hashtab.h"
|
|
|
6d55b5 |
#include <errno.h>
|
|
|
6d55b5 |
|
|
|
6d55b5 |
static krb5_error_code KRB5_CALLCONV krb5_mcc_close
|
|
|
6d55b5 |
@@ -118,12 +119,6 @@ typedef struct _krb5_mcc_data {
|
|
|
6d55b5 |
int generation; /* Incremented at each initialize */
|
|
|
6d55b5 |
} krb5_mcc_data;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
-/* List of memory caches. */
|
|
|
6d55b5 |
-typedef struct krb5_mcc_list_node {
|
|
|
6d55b5 |
- struct krb5_mcc_list_node *next;
|
|
|
6d55b5 |
- krb5_mcc_data *cache;
|
|
|
6d55b5 |
-} krb5_mcc_list_node;
|
|
|
6d55b5 |
-
|
|
|
6d55b5 |
/* Iterator over credentials in a memory cache. */
|
|
|
6d55b5 |
struct mcc_cursor {
|
|
|
6d55b5 |
int generation;
|
|
|
6d55b5 |
@@ -136,10 +131,27 @@ struct krb5_mcc_ptcursor_data {
|
|
|
6d55b5 |
};
|
|
|
6d55b5 |
|
|
|
6d55b5 |
k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
|
|
|
6d55b5 |
-static krb5_mcc_list_node *mcc_head = 0;
|
|
|
6d55b5 |
+static struct k5_hashtab *mcc_hashtab = NULL;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
static void update_mcc_change_time(krb5_mcc_data *);
|
|
|
6d55b5 |
|
|
|
6d55b5 |
+/* Ensure that mcc_hashtab is initialized. Call with krb5int_mcc_mutex
|
|
|
6d55b5 |
+ * locked. */
|
|
|
6d55b5 |
+static krb5_error_code
|
|
|
6d55b5 |
+init_table(krb5_context context)
|
|
|
6d55b5 |
+{
|
|
|
6d55b5 |
+ krb5_error_code ret;
|
|
|
6d55b5 |
+ uint8_t seed[K5_HASH_SEED_LEN];
|
|
|
6d55b5 |
+ krb5_data d = make_data(seed, sizeof(seed));
|
|
|
6d55b5 |
+
|
|
|
6d55b5 |
+ if (mcc_hashtab != NULL)
|
|
|
6d55b5 |
+ return 0;
|
|
|
6d55b5 |
+ ret = krb5_c_random_make_octets(context, &d);
|
|
|
6d55b5 |
+ if (ret)
|
|
|
6d55b5 |
+ return ret;
|
|
|
6d55b5 |
+ return k5_hashtab_create(seed, 64, &mcc_hashtab);
|
|
|
6d55b5 |
+}
|
|
|
6d55b5 |
+
|
|
|
6d55b5 |
/* Remove creds from d, invalidate any existing cursors, and unset the client
|
|
|
6d55b5 |
* principal. The caller is responsible for locking. */
|
|
|
6d55b5 |
static void
|
|
|
6d55b5 |
@@ -230,21 +242,13 @@ krb5_mcc_close(krb5_context context, krb5_ccache id)
|
|
|
6d55b5 |
krb5_error_code KRB5_CALLCONV
|
|
|
6d55b5 |
krb5_mcc_destroy(krb5_context context, krb5_ccache id)
|
|
|
6d55b5 |
{
|
|
|
6d55b5 |
- krb5_mcc_list_node **curr, *node;
|
|
|
6d55b5 |
krb5_mcc_data *d = id->data;
|
|
|
6d55b5 |
krb5_boolean removed_from_table = FALSE;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
+ /* Remove this node from the table if it is still present. */
|
|
|
6d55b5 |
k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
|
|
|
6d55b5 |
-
|
|
|
6d55b5 |
- for (curr = &mcc_head; *curr; curr = &(*curr)->next) {
|
|
|
6d55b5 |
- if ((*curr)->cache == d) {
|
|
|
6d55b5 |
- node = *curr;
|
|
|
6d55b5 |
- *curr = node->next;
|
|
|
6d55b5 |
- free(node);
|
|
|
6d55b5 |
- removed_from_table = TRUE;
|
|
|
6d55b5 |
- break;
|
|
|
6d55b5 |
- }
|
|
|
6d55b5 |
- }
|
|
|
6d55b5 |
+ if (k5_hashtab_remove(mcc_hashtab, d->name, strlen(d->name)))
|
|
|
6d55b5 |
+ removed_from_table = TRUE;
|
|
|
6d55b5 |
k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
|
|
|
6d55b5 |
|
|
|
6d55b5 |
/* Empty the cache and remove the reference for the table slot. There will
|
|
|
6d55b5 |
@@ -289,16 +293,13 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
|
|
|
6d55b5 |
{
|
|
|
6d55b5 |
krb5_os_context os_ctx = &context->os_context;
|
|
|
6d55b5 |
krb5_ccache lid;
|
|
|
6d55b5 |
- krb5_mcc_list_node *ptr;
|
|
|
6d55b5 |
krb5_error_code err;
|
|
|
6d55b5 |
krb5_mcc_data *d;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
|
|
|
6d55b5 |
- for (ptr = mcc_head; ptr; ptr=ptr->next)
|
|
|
6d55b5 |
- if (!strcmp(ptr->cache->name, residual))
|
|
|
6d55b5 |
- break;
|
|
|
6d55b5 |
- if (ptr != NULL) {
|
|
|
6d55b5 |
- d = ptr->cache;
|
|
|
6d55b5 |
+ init_table(context);
|
|
|
6d55b5 |
+ d = k5_hashtab_get(mcc_hashtab, residual, strlen(residual));
|
|
|
6d55b5 |
+ if (d != NULL) {
|
|
|
6d55b5 |
k5_cc_mutex_lock(context, &d->lock);
|
|
|
6d55b5 |
d->refcount++;
|
|
|
6d55b5 |
k5_cc_mutex_unlock(context, &d->lock);
|
|
|
6d55b5 |
@@ -438,18 +439,17 @@ krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *curso
|
|
|
6d55b5 |
}
|
|
|
6d55b5 |
|
|
|
6d55b5 |
/*
|
|
|
6d55b5 |
- * Utility routine: Creates the back-end data for a memory cache, and threads
|
|
|
6d55b5 |
- * it into the global linked list. Give the new object two references, one for
|
|
|
6d55b5 |
- * the table slot and one for the caller's handle.
|
|
|
6d55b5 |
+ * Utility routine: Creates the back-end data for a memory cache, and adds it
|
|
|
6d55b5 |
+ * to the global table. Give the new object two references, one for the table
|
|
|
6d55b5 |
+ * slot and one for the caller's handle.
|
|
|
6d55b5 |
*
|
|
|
6d55b5 |
- * Call with the global list lock held.
|
|
|
6d55b5 |
+ * Call with the global table lock held.
|
|
|
6d55b5 |
*/
|
|
|
6d55b5 |
static krb5_error_code
|
|
|
6d55b5 |
new_mcc_data (const char *name, krb5_mcc_data **dataptr)
|
|
|
6d55b5 |
{
|
|
|
6d55b5 |
krb5_error_code err;
|
|
|
6d55b5 |
krb5_mcc_data *d;
|
|
|
6d55b5 |
- krb5_mcc_list_node *n;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
d = malloc(sizeof(krb5_mcc_data));
|
|
|
6d55b5 |
if (d == NULL)
|
|
|
6d55b5 |
@@ -476,18 +476,13 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
|
|
|
6d55b5 |
d->generation = 0;
|
|
|
6d55b5 |
update_mcc_change_time(d);
|
|
|
6d55b5 |
|
|
|
6d55b5 |
- n = malloc(sizeof(krb5_mcc_list_node));
|
|
|
6d55b5 |
- if (n == NULL) {
|
|
|
6d55b5 |
+ if (k5_hashtab_add(mcc_hashtab, d->name, strlen(d->name), d) != 0) {
|
|
|
6d55b5 |
free(d->name);
|
|
|
6d55b5 |
k5_cc_mutex_destroy(&d->lock);
|
|
|
6d55b5 |
free(d);
|
|
|
6d55b5 |
return KRB5_CC_NOMEM;
|
|
|
6d55b5 |
}
|
|
|
6d55b5 |
|
|
|
6d55b5 |
- n->cache = d;
|
|
|
6d55b5 |
- n->next = mcc_head;
|
|
|
6d55b5 |
- mcc_head = n;
|
|
|
6d55b5 |
-
|
|
|
6d55b5 |
*dataptr = d;
|
|
|
6d55b5 |
return 0;
|
|
|
6d55b5 |
}
|
|
|
6d55b5 |
@@ -522,11 +517,10 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
|
|
|
6d55b5 |
lid->ops = &krb5_mcc_ops;
|
|
|
6d55b5 |
|
|
|
6d55b5 |
k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
|
|
|
6d55b5 |
+ init_table(context);
|
|
|
6d55b5 |
|
|
|
6d55b5 |
/* Check for uniqueness with mutex locked to avoid race conditions */
|
|
|
6d55b5 |
while (1) {
|
|
|
6d55b5 |
- krb5_mcc_list_node *ptr;
|
|
|
6d55b5 |
-
|
|
|
6d55b5 |
err = krb5int_random_string (context, uniquename, sizeof (uniquename));
|
|
|
6d55b5 |
if (err) {
|
|
|
6d55b5 |
k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
|
|
|
6d55b5 |
@@ -534,12 +528,9 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
|
|
|
6d55b5 |
return err;
|
|
|
6d55b5 |
}
|
|
|
6d55b5 |
|
|
|
6d55b5 |
- for (ptr = mcc_head; ptr; ptr=ptr->next) {
|
|
|
6d55b5 |
- if (!strcmp(ptr->cache->name, uniquename)) {
|
|
|
6d55b5 |
- break; /* got a match, loop again */
|
|
|
6d55b5 |
- }
|
|
|
6d55b5 |
- }
|
|
|
6d55b5 |
- if (!ptr) break; /* got to the end without finding a match */
|
|
|
6d55b5 |
+ if (k5_hashtab_get(mcc_hashtab, uniquename,
|
|
|
6d55b5 |
+ strlen(uniquename)) == NULL)
|
|
|
6d55b5 |
+ break;
|
|
|
6d55b5 |
}
|
|
|
6d55b5 |
|
|
|
6d55b5 |
err = new_mcc_data(uniquename, &d);
|