From 601213491f50599754079bac942aa48813606653 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 27 Jul 2010 22:25:47 +0200 Subject: Drop left-over code for data objects --- ncr-int.h | 1 - ncr.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 2af794f..733bb77 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -98,7 +98,6 @@ struct list_sem_st { * are here. */ struct ncr_lists { - struct list_sem_st data; struct list_sem_st key; /* sessions */ diff --git a/ncr.c b/ncr.c index 87bd052..624d217 100644 --- a/ncr.c +++ b/ncr.c @@ -52,9 +52,6 @@ void* ncr_init_lists(void) memset(lst, 0, sizeof(*lst)); - init_MUTEX(&lst->data.sem); - INIT_LIST_HEAD(&lst->data.list); - init_MUTEX(&lst->key.sem); INIT_LIST_HEAD(&lst->key.list); -- cgit From df4c072acb675a4c89882e3c92442978cf94eedd Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 27 Jul 2010 23:29:21 +0200 Subject: Use ncr_lists instead of list_sem_st in intefaces Should result in no functionality change. This makes the code marginally more effective (reducing the number of "&lst->key" and "&lst->sessions" operations in the code, and moving them toward dereferences where they can be combined with member accesses), and more type-safe (prevents mixing the key and session list in most places because they the difference is only in the low-level accessor functions). Most importantly, this allows replacing list_sem_st without having to touch most of the functions again. --- ncr-int.h | 46 +++++++++++++++++++++++----------------------- ncr-key-wrap.c | 20 ++++++++++---------- ncr-key.c | 52 ++++++++++++++++++++++++++++++---------------------- ncr-sessions.c | 53 +++++++++++++++++++++++++++++------------------------ ncr.c | 28 ++++++++++++++-------------- 5 files changed, 106 insertions(+), 93 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 2af794f..7cd82eb 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -112,26 +112,26 @@ int ncr_ioctl(struct ncr_lists*, struct file *filp, unsigned int cmd, unsigned long arg); /* key derivation */ -int ncr_key_derive(struct list_sem_st* key_lst, void __user* arg); +int ncr_key_derive(struct ncr_lists *lst, void __user* arg); /* key handling */ -int ncr_key_init(struct list_sem_st*, void __user* arg); -int ncr_key_deinit(struct list_sem_st*, void __user* arg); -int ncr_key_export(struct list_sem_st* key_lst,void __user* arg); -int ncr_key_import(struct list_sem_st* key_lst,void __user* arg); -void ncr_key_list_deinit(struct list_sem_st* lst); -int ncr_key_generate(struct list_sem_st* data_lst, void __user* arg); -int ncr_key_info(struct list_sem_st*, void __user* arg); - -int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg); -int ncr_key_derive(struct list_sem_st*, void __user* arg); -int ncr_key_get_public(struct list_sem_st* lst, void __user* arg); - -int ncr_key_item_get_read(struct key_item_st**st, struct list_sem_st* lst, +int ncr_key_init(struct ncr_lists *lst, void __user* arg); +int ncr_key_deinit(struct ncr_lists *lst, void __user* arg); +int ncr_key_export(struct ncr_lists *lst, void __user* arg); +int ncr_key_import(struct ncr_lists *lst, void __user* arg); +void ncr_key_list_deinit(struct ncr_lists *lst); +int ncr_key_generate(struct ncr_lists *lst, void __user* arg); +int ncr_key_info(struct ncr_lists *lst, void __user* arg); + +int ncr_key_generate_pair(struct ncr_lists *lst, void __user* arg); +int ncr_key_derive(struct ncr_lists *lst, void __user* arg); +int ncr_key_get_public(struct ncr_lists *lst, void __user* arg); + +int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst, ncr_key_t desc); /* get key item for writing */ -int ncr_key_item_get_write( struct key_item_st** st, - struct list_sem_st* lst, ncr_key_t desc); +int ncr_key_item_get_write( struct key_item_st** st, + struct ncr_lists *lst, ncr_key_t desc); void _ncr_key_item_put( struct key_item_st* item); typedef enum { @@ -143,16 +143,16 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); void ncr_limits_init(void); void ncr_limits_deinit(void); -int ncr_key_wrap(struct list_sem_st* keys, void __user* arg); -int ncr_key_unwrap(struct list_sem_st*, void __user* arg); -int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg); -int ncr_key_storage_unwrap(struct list_sem_st*, void __user* arg); +int ncr_key_wrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg); /* sessions */ -struct session_item_st* ncr_session_new(struct list_sem_st* lst); +struct session_item_st* ncr_session_new(struct ncr_lists *lst); void _ncr_sessions_item_put( struct session_item_st* item); -struct session_item_st* ncr_sessions_item_get( struct list_sem_st* lst, ncr_session_t desc); -void ncr_sessions_list_deinit(struct list_sem_st* lst); +struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc); +void ncr_sessions_list_deinit(struct ncr_lists *lst); int ncr_session_init(struct ncr_lists* lists, void __user* arg); int ncr_session_update(struct ncr_lists* lists, void __user* arg); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 5d3ec67..b66b731 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -427,7 +427,7 @@ cleanup: return ret; } -int ncr_key_wrap(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_wrap(struct ncr_lists *lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; @@ -441,7 +441,7 @@ int ret; return -EFAULT; } - ret = ncr_key_item_get_read( &wkey, key_lst, wrap.keytowrap); + ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); if (ret < 0) { err(); return ret; @@ -453,7 +453,7 @@ int ret; goto fail; } - ret = ncr_key_item_get_read( &key, key_lst, wrap.key); + ret = ncr_key_item_get_read( &key, lst, wrap.key); if (ret < 0) { err(); goto fail; @@ -510,7 +510,7 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_unwrap(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; @@ -524,13 +524,13 @@ int ret; return -EFAULT; } - ret = ncr_key_item_get_write( &wkey, key_lst, wrap.keytowrap); + ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); if (ret < 0) { err(); return ret; } - ret = ncr_key_item_get_read( &key, key_lst, wrap.key); + ret = ncr_key_item_get_read( &key, lst, wrap.key); if (ret < 0) { err(); goto fail; @@ -572,7 +572,7 @@ fail: return ret; } -int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; @@ -592,7 +592,7 @@ int ret; return -EFAULT; } - ret = ncr_key_item_get_read( &wkey, key_lst, wrap.keytowrap); + ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); if (ret < 0) { err(); return ret; @@ -648,7 +648,7 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_storage_unwrap(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; @@ -667,7 +667,7 @@ int ret; return -EFAULT; } - ret = ncr_key_item_get_write( &wkey, key_lst, wrap.keytowrap); + ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); if (ret < 0) { err(); return ret; diff --git a/ncr-key.c b/ncr-key.c index e0361bc..c39fa19 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -40,18 +40,18 @@ static void _ncr_key_unlink_item(struct key_item_st *item) _ncr_key_item_put( item); /* decrement ref count */ } -void ncr_key_list_deinit(struct list_sem_st* lst) +void ncr_key_list_deinit(struct ncr_lists *lst_) { - if(lst) { - struct key_item_st * item, *tmp; + struct list_sem_st *lst; + struct key_item_st * item, *tmp; - down(&lst->sem); + lst = &lst_->key; + down(&lst->sem); - list_for_each_entry_safe(item, tmp, &lst->list, list) { - _ncr_key_unlink_item(item); - } - up(&lst->sem); + list_for_each_entry_safe(item, tmp, &lst->list, list) { + _ncr_key_unlink_item(item); } + up(&lst->sem); } /* must be called with data semaphore down @@ -70,12 +70,14 @@ int mx = 1; } /* returns the data item corresponding to desc */ -int ncr_key_item_get_read(struct key_item_st**st, struct list_sem_st* lst, +int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst_, ncr_key_t desc) { +struct list_sem_st *lst; struct key_item_st* item; int ret; + lst = &lst_->key; *st = NULL; down(&lst->sem); @@ -107,11 +109,13 @@ exit: * is in use. */ int ncr_key_item_get_write( struct key_item_st** st, - struct list_sem_st* lst, ncr_key_t desc) + struct ncr_lists *lst_, ncr_key_t desc) { +struct list_sem_st *lst; struct key_item_st* item; int ret; + lst = &lst_->key; *st = NULL; down(&lst->sem); @@ -157,12 +161,14 @@ void _ncr_key_item_put( struct key_item_st* item) } } -int ncr_key_init(struct list_sem_st* lst, void __user* arg) +int ncr_key_init(struct ncr_lists *lst_, void __user* arg) { + struct list_sem_st *lst; ncr_key_t desc; struct key_item_st* key; int ret; + lst = &lst_->key; ret = ncr_limits_add_and_check(current_euid(), task_pid_nr(current), LIMIT_TYPE_KEY); if (ret < 0) { err(); @@ -207,11 +213,13 @@ err_limits: } -int ncr_key_deinit(struct list_sem_st* lst, void __user* arg) +int ncr_key_deinit(struct ncr_lists *lst_, void __user* arg) { + struct list_sem_st *lst; ncr_key_t desc; struct key_item_st * item, *tmp; + lst = &lst_->key; if (unlikely(copy_from_user(&desc, arg, sizeof(desc)))) { err(); return -EFAULT; @@ -234,7 +242,7 @@ int ncr_key_deinit(struct list_sem_st* lst, void __user* arg) /* "exports" a key to a data item. If the key is not exportable * to userspace then the data item will also not be. */ -int ncr_key_export(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_export(struct ncr_lists *lst, void __user* arg) { struct ncr_key_data_st data; struct key_item_st* item = NULL; @@ -247,7 +255,7 @@ int ret; return -EFAULT; } - ret = ncr_key_item_get_read( &item, key_lst, data.key); + ret = ncr_key_item_get_read( &item, lst, data.key); if (ret < 0) { err(); return ret; @@ -329,7 +337,7 @@ fail: /* "imports" a key from a data item. If the key is not exportable * to userspace then the key item will also not be. */ -int ncr_key_import(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_import(struct ncr_lists *lst, void __user* arg) { struct ncr_key_data_st data; struct key_item_st* item = NULL; @@ -342,7 +350,7 @@ size_t tmp_size; return -EFAULT; } - ret = ncr_key_item_get_write( &item, key_lst, data.key); + ret = ncr_key_item_get_write( &item, lst, data.key); if (ret < 0) { err(); return ret; @@ -438,7 +446,7 @@ static void ncr_key_clear(struct key_item_st* item) /* Generate a secret key */ -int ncr_key_generate(struct list_sem_st* lst, void __user* arg) +int ncr_key_generate(struct ncr_lists *lst, void __user* arg) { struct ncr_key_generate_st gen; struct key_item_st* item = NULL; @@ -500,7 +508,7 @@ fail: return ret; } -int ncr_key_info(struct list_sem_st* lst, void __user* arg) +int ncr_key_info(struct ncr_lists *lst, void __user* arg) { struct ncr_key_info_st info; struct key_item_st* item = NULL; @@ -535,7 +543,7 @@ fail: return ret; } -int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg) +int ncr_key_generate_pair(struct ncr_lists *lst, void __user* arg) { struct ncr_key_generate_st gen; struct key_item_st* private = NULL; @@ -602,7 +610,7 @@ fail: /* "exports" a key to a data item. If the key is not exportable * to userspace then the data item will also not be. */ -int ncr_key_derive(struct list_sem_st* key_lst, void __user* arg) +int ncr_key_derive(struct ncr_lists *lst, void __user* arg) { struct ncr_key_derivation_params_st data; int ret; @@ -614,13 +622,13 @@ struct key_item_st* newkey = NULL; return -EFAULT; } - ret = ncr_key_item_get_read( &key, key_lst, data.key); + ret = ncr_key_item_get_read( &key, lst, data.key); if (ret < 0) { err(); return ret; } - ret = ncr_key_item_get_write( &newkey, key_lst, data.newkey); + ret = ncr_key_item_get_write( &newkey, lst, data.newkey); if (ret < 0) { err(); goto fail; diff --git a/ncr-sessions.c b/ncr-sessions.c index c5b31ac..ab065fa 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,22 +31,21 @@ #include static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); +static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); -void ncr_sessions_list_deinit(struct list_sem_st* lst) +void ncr_sessions_list_deinit(struct ncr_lists *lst_) { - if(lst) { - struct session_item_st * item, *tmp; + struct list_sem_st *lst; + struct session_item_st * item, *tmp; - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - list_del(&item->list); - _ncr_sessions_item_put( item); /* decrement ref count */ - } - up(&lst->sem); + lst = &lst_->sessions; + down(&lst->sem); + list_for_each_entry_safe(item, tmp, &lst->list, list) { + list_del(&item->list); + _ncr_sessions_item_put( item); /* decrement ref count */ } + up(&lst->sem); } /* must be called with data semaphore down @@ -65,10 +64,12 @@ int mx = 1; } /* returns the data item corresponding to desc */ -struct session_item_st* ncr_sessions_item_get( struct list_sem_st* lst, ncr_session_t desc) +struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst_, ncr_session_t desc) { +struct list_sem_st *lst; struct session_item_st* item; + lst = &lst_->sessions; down(&lst->sem); list_for_each_entry(item, &lst->list, list) { if (item->desc == desc) { @@ -97,10 +98,12 @@ void _ncr_sessions_item_put( struct session_item_st* item) } } -struct session_item_st* ncr_session_new(struct list_sem_st* lst) +struct session_item_st* ncr_session_new(struct ncr_lists *lst_) { + struct list_sem_st *lst; struct session_item_st* sess; + lst = &lst_->sessions; sess = kzalloc(sizeof(*sess), GFP_KERNEL); if (sess == NULL) { err(); @@ -226,7 +229,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses int ret; const struct algo_properties_st *sign_hash; - ns = ncr_session_new(&lists->sessions); + ns = ncr_session_new(lists); if (ns == NULL) { err(); return -EINVAL; @@ -250,7 +253,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } /* read key */ - ret = ncr_key_item_get_read( &ns->key, &lists->key, session->key); + ret = ncr_key_item_get_read( &ns->key, lists, session->key); if (ret < 0) { err(); goto fail; @@ -318,7 +321,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } else { /* read key */ - ret = ncr_key_item_get_read( &ns->key, &lists->key, session->key); + ret = ncr_key_item_get_read( &ns->key, lists, session->key); if (ret < 0) { err(); goto fail; @@ -388,7 +391,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses fail: if (ret < 0) { - _ncr_session_remove(&lists->sessions, ns->desc); + _ncr_session_remove(lists, ns->desc); } return ret; @@ -413,7 +416,7 @@ int ncr_session_init(struct ncr_lists* lists, void __user* arg) ret = copy_to_user( arg, &session, sizeof(session)); if (unlikely(ret)) { err(); - _ncr_session_remove(&lists->sessions, session.ses); + _ncr_session_remove(lists, session.ses); return -EFAULT; } return ret; @@ -476,10 +479,12 @@ int ret; return 0; } -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) +static void _ncr_session_remove(struct ncr_lists *lst_, ncr_session_t desc) { + struct list_sem_st* lst; struct session_item_st * item, *tmp; + lst = &lst_->sessions; down(&lst->sem); list_for_each_entry_safe(item, tmp, &lst->list, list) { @@ -627,7 +632,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st unsigned osg_cnt=0, isg_cnt=0; size_t isg_size, osg_size; - sess = ncr_sessions_item_get( &lists->sessions, op->ses); + sess = ncr_sessions_item_get(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; @@ -747,7 +752,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* void __user * udata = NULL; size_t *udata_size; - sess = ncr_sessions_item_get( &lists->sessions, op->ses); + sess = ncr_sessions_item_get(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; @@ -897,7 +902,7 @@ fail: } _ncr_sessions_item_put(sess); - _ncr_session_remove(&lists->sessions, op->ses); + _ncr_session_remove(lists, op->ses); return ret; } @@ -910,14 +915,14 @@ static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_o struct session_item_st* sess; struct key_item_st* key = NULL; - sess = ncr_sessions_item_get( &lists->sessions, op->ses); + sess = ncr_sessions_item_get(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; } /* read key */ - ret = ncr_key_item_get_read( &key, &lists->key, op->data.kdata.input); + ret = ncr_key_item_get_read( &key, lists, op->data.kdata.input); if (ret < 0) { err(); goto fail; diff --git a/ncr.c b/ncr.c index 87bd052..5bf8c5e 100644 --- a/ncr.c +++ b/ncr.c @@ -67,8 +67,8 @@ void* ncr_init_lists(void) void ncr_deinit_lists(struct ncr_lists *lst) { if(lst) { - ncr_key_list_deinit(&lst->key); - ncr_sessions_list_deinit(&lst->sessions); + ncr_key_list_deinit(lst); + ncr_sessions_list_deinit(lst); kfree(lst); } } @@ -127,25 +127,25 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, switch (cmd) { case NCRIO_KEY_INIT: - return ncr_key_init(&lst->key, arg); + return ncr_key_init(lst, arg); case NCRIO_KEY_DEINIT: - return ncr_key_deinit(&lst->key, arg); + return ncr_key_deinit(lst, arg); case NCRIO_KEY_GENERATE: - return ncr_key_generate(&lst->key, arg); + return ncr_key_generate(lst, arg); case NCRIO_KEY_EXPORT: - return ncr_key_export(&lst->key, arg); + return ncr_key_export(lst, arg); case NCRIO_KEY_IMPORT: - return ncr_key_import(&lst->key, arg); + return ncr_key_import(lst, arg); case NCRIO_KEY_GET_INFO: - return ncr_key_info(&lst->key, arg); + return ncr_key_info(lst, arg); case NCRIO_KEY_WRAP: - return ncr_key_wrap(&lst->key, arg); + return ncr_key_wrap(lst, arg); case NCRIO_KEY_UNWRAP: - return ncr_key_unwrap(&lst->key, arg); + return ncr_key_unwrap(lst, arg); case NCRIO_KEY_STORAGE_WRAP: - return ncr_key_storage_wrap(&lst->key, arg); + return ncr_key_storage_wrap(lst, arg); case NCRIO_KEY_STORAGE_UNWRAP: - return ncr_key_storage_unwrap(&lst->key, arg); + return ncr_key_storage_unwrap(lst, arg); case NCRIO_SESSION_INIT: return ncr_session_init(lst, arg); case NCRIO_SESSION_UPDATE: @@ -158,9 +158,9 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); case NCRIO_KEY_GENERATE_PAIR: - return ncr_key_generate_pair(&lst->key, arg); + return ncr_key_generate_pair(lst, arg); case NCRIO_KEY_DERIVE: - return ncr_key_derive(&lst->key, arg); + return ncr_key_derive(lst, arg); default: return -EINVAL; } -- cgit From 16a6c980b405924a26fec8508bb6181897402bec Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 00:17:24 +0200 Subject: Use for key ID allocation and lookup --- ncr-int.h | 6 +- ncr-key.c | 188 +++++++++++++++++++++++++++----------------------------------- ncr.c | 4 +- 3 files changed, 88 insertions(+), 110 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 7cd82eb..84761ff 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -1,6 +1,8 @@ #ifndef NCR_INT_H # define NCR_INT_H +#include +#include #include "ncr.h" #include #include "cryptodev_int.h" @@ -58,7 +60,6 @@ struct session_item_st { }; struct key_item_st { - struct list_head list; /* This object is also not protected from concurrent access. */ ncr_key_type_t type; @@ -99,7 +100,8 @@ struct list_sem_st { */ struct ncr_lists { struct list_sem_st data; - struct list_sem_st key; + struct mutex key_idr_mutex; + struct idr key_idr; /* sessions */ struct list_sem_st sessions; diff --git a/ncr-key.c b/ncr-key.c index c39fa19..79adf77 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -33,75 +33,54 @@ static void ncr_key_clear(struct key_item_st* item); -/* must be called with data semaphore down */ -static void _ncr_key_unlink_item(struct key_item_st *item) +static int key_list_deinit_fn(int id, void *item, void *unused) { - list_del(&item->list); - _ncr_key_item_put( item); /* decrement ref count */ + (void)unused; + _ncr_key_item_put(item); + return 0; } -void ncr_key_list_deinit(struct ncr_lists *lst_) +void ncr_key_list_deinit(struct ncr_lists *lst) { - struct list_sem_st *lst; - struct key_item_st * item, *tmp; - - lst = &lst_->key; - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - _ncr_key_unlink_item(item); - } - up(&lst->sem); -} - -/* must be called with data semaphore down - */ -static ncr_key_t _ncr_key_get_new_desc( struct list_sem_st* lst) -{ -struct key_item_st* item; -int mx = 1; - - list_for_each_entry(item, &lst->list, list) { - mx = max(mx, item->desc); - } - mx++; - - return mx; + /* The mutex is not necessary, but doesn't hurt and makes it easier to + verify locking correctness. */ + mutex_lock(&lst->key_idr_mutex); + idr_for_each(&lst->key_idr, key_list_deinit_fn, NULL); + idr_remove_all(&lst->key_idr); + idr_destroy(&lst->key_idr); + mutex_unlock(&lst->key_idr_mutex); } /* returns the data item corresponding to desc */ -int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst_, +int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst, ncr_key_t desc) { -struct list_sem_st *lst; struct key_item_st* item; int ret; - lst = &lst_->key; *st = NULL; - down(&lst->sem); - list_for_each_entry(item, &lst->list, list) { - if (item->desc == desc) { - atomic_inc(&item->refcnt); - - if (atomic_read(&item->writer) != 0) { - /* writer in place busy */ - atomic_dec(&item->refcnt); - ret = -EBUSY; - goto exit; - } - - *st = item; - ret = 0; - goto exit; - } + mutex_lock(&lst->key_idr_mutex); + item = idr_find(&lst->key_idr, desc); + if (item == NULL) { + err(); + ret = -EINVAL; + goto exit; + } + atomic_inc(&item->refcnt); + + if (atomic_read(&item->writer) != 0) { + /* writer in place busy */ + atomic_dec(&item->refcnt); + ret = -EBUSY; + goto exit; } - err(); - ret = -EINVAL; + *st = item; + ret = 0; + exit: - up(&lst->sem); + mutex_unlock(&lst->key_idr_mutex); return ret; } @@ -109,44 +88,40 @@ exit: * is in use. */ int ncr_key_item_get_write( struct key_item_st** st, - struct ncr_lists *lst_, ncr_key_t desc) + struct ncr_lists *lst, ncr_key_t desc) { -struct list_sem_st *lst; struct key_item_st* item; int ret; - lst = &lst_->key; *st = NULL; - down(&lst->sem); - list_for_each_entry(item, &lst->list, list) { - if (item->desc == desc) { - /* do not return items that are in use already */ + mutex_lock(&lst->key_idr_mutex); + item = idr_find(&lst->key_idr, desc); + if (item == NULL) { + err(); + ret = -EINVAL; + goto exit; + } + /* do not return items that are in use already */ - if (atomic_add_unless(&item->writer, 1, 1)==0) { - /* another writer so busy */ - ret = -EBUSY; - goto exit; - } - - if (atomic_add_unless(&item->refcnt, 1, 2)==0) { - /* some reader is active so busy */ - atomic_dec(&item->writer); - ret = -EBUSY; - goto exit; - } + if (atomic_add_unless(&item->writer, 1, 1)==0) { + /* another writer so busy */ + ret = -EBUSY; + goto exit; + } - *st = item; - ret = 0; - goto exit; - } + if (atomic_add_unless(&item->refcnt, 1, 2)==0) { + /* some reader is active so busy */ + atomic_dec(&item->writer); + ret = -EBUSY; + goto exit; } - err(); - ret = -EINVAL; + *st = item; + ret = 0; exit: - up(&lst->sem); + mutex_unlock(&lst->key_idr_mutex); return ret; } @@ -161,14 +136,26 @@ void _ncr_key_item_put( struct key_item_st* item) } } -int ncr_key_init(struct ncr_lists *lst_, void __user* arg) +static void _ncr_key_remove(struct ncr_lists *lst, ncr_key_t desc) +{ + struct key_item_st * item; + + mutex_lock(&lst->key_idr_mutex); + item = idr_find(&lst->key_idr, desc); + if (item != NULL) + idr_remove(&lst->key_idr, desc); /* Steal the reference */ + mutex_unlock(&lst->key_idr_mutex); + + if (item != NULL) + _ncr_key_item_put(item); +} + +int ncr_key_init(struct ncr_lists *lst, void __user* arg) { - struct list_sem_st *lst; ncr_key_t desc; struct key_item_st* key; int ret; - lst = &lst_->key; ret = ncr_limits_add_and_check(current_euid(), task_pid_nr(current), LIMIT_TYPE_KEY); if (ret < 0) { err(); @@ -186,23 +173,25 @@ int ncr_key_init(struct ncr_lists *lst_, void __user* arg) atomic_set(&key->refcnt, 1); atomic_set(&key->writer, 0); - - down(&lst->sem); - - key->desc = _ncr_key_get_new_desc(lst); key->uid = current_euid(); key->pid = task_pid_nr(current); - list_add(&key->list, &lst->list); - - up(&lst->sem); + mutex_lock(&lst->key_idr_mutex); + /* idr_pre_get() should preallocate enough, and, due to key_idr_mutex, + nobody else can use the preallocated data. Therefore the loop + recommended in idr_get_new() documentation is not necessary. */ + if (idr_pre_get(&lst->key_idr, GFP_KERNEL) == 0 || + idr_get_new(&lst->key_idr, key, &key->desc) != 0) { + mutex_unlock(&lst->key_idr_mutex); + _ncr_key_item_put(key); + return -ENOMEM; + } + mutex_unlock(&lst->key_idr_mutex); desc = key->desc; ret = copy_to_user(arg, &desc, sizeof(desc)); if (unlikely(ret)) { - down(&lst->sem); - _ncr_key_unlink_item(key); - up(&lst->sem); + _ncr_key_remove(lst, desc); return -EFAULT; } return ret; @@ -212,29 +201,16 @@ err_limits: return ret; } - -int ncr_key_deinit(struct ncr_lists *lst_, void __user* arg) +int ncr_key_deinit(struct ncr_lists *lst, void __user* arg) { - struct list_sem_st *lst; ncr_key_t desc; - struct key_item_st * item, *tmp; - lst = &lst_->key; if (unlikely(copy_from_user(&desc, arg, sizeof(desc)))) { err(); return -EFAULT; } - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - if(item->desc == desc) { - _ncr_key_unlink_item(item); - break; - } - } - - up(&lst->sem); + _ncr_key_remove(lst, desc); return 0; } diff --git a/ncr.c b/ncr.c index 5bf8c5e..86571d7 100644 --- a/ncr.c +++ b/ncr.c @@ -55,8 +55,8 @@ void* ncr_init_lists(void) init_MUTEX(&lst->data.sem); INIT_LIST_HEAD(&lst->data.list); - init_MUTEX(&lst->key.sem); - INIT_LIST_HEAD(&lst->key.list); + mutex_init(&lst->key_idr_mutex); + idr_init(&lst->key_idr); init_MUTEX(&lst->sessions.sem); INIT_LIST_HEAD(&lst->sessions.list); -- cgit From bc64c437410a2339eb1437280c9761c565032d4b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 01:11:30 +0200 Subject: Use for session ID allocation and lookup --- ncr-int.h | 5 ++- ncr-sessions.c | 112 +++++++++++++++++++++++++-------------------------------- ncr.c | 4 +-- 3 files changed, 52 insertions(+), 69 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 84761ff..ba0b69b 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -32,8 +32,6 @@ struct algo_properties_st { }; struct session_item_st { - struct list_head list; - const struct algo_properties_st *algorithm; ncr_crypto_op_t op; @@ -104,7 +102,8 @@ struct ncr_lists { struct idr key_idr; /* sessions */ - struct list_sem_st sessions; + struct mutex session_idr_mutex; + struct idr session_idr; }; void* ncr_init_lists(void); diff --git a/ncr-sessions.c b/ncr-sessions.c index ab065fa..1f2c251 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -33,52 +33,37 @@ static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); -void ncr_sessions_list_deinit(struct ncr_lists *lst_) +static int session_list_deinit_fn(int id, void *item, void *unused) { - struct list_sem_st *lst; - struct session_item_st * item, *tmp; - - lst = &lst_->sessions; - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - list_del(&item->list); - _ncr_sessions_item_put( item); /* decrement ref count */ - } - up(&lst->sem); + (void)unused; + _ncr_sessions_item_put(item); + return 0; } -/* must be called with data semaphore down - */ -static ncr_session_t _ncr_sessions_get_new_desc( struct list_sem_st* lst) +void ncr_sessions_list_deinit(struct ncr_lists *lst) { -struct session_item_st* item; -int mx = 1; - - list_for_each_entry(item, &lst->list, list) { - mx = max(mx, item->desc); - } - mx++; - - return mx; + /* The mutex is not necessary, but doesn't hurt and makes it easier to + verify locking correctness. */ + mutex_lock(&lst->session_idr_mutex); + idr_for_each(&lst->session_idr, session_list_deinit_fn, NULL); + idr_remove_all(&lst->session_idr); + idr_destroy(&lst->session_idr); + mutex_unlock(&lst->session_idr_mutex); } /* returns the data item corresponding to desc */ -struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst_, ncr_session_t desc) +struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc) { -struct list_sem_st *lst; struct session_item_st* item; - lst = &lst_->sessions; - down(&lst->sem); - list_for_each_entry(item, &lst->list, list) { - if (item->desc == desc) { - atomic_inc(&item->refcnt); - up(&lst->sem); - return item; - } + mutex_lock(&lst->session_idr_mutex); + item = idr_find(&lst->session_idr, desc); + if (item != NULL) { + atomic_inc(&item->refcnt); + mutex_unlock(&lst->session_idr_mutex); + return item; } - up(&lst->sem); + mutex_unlock(&lst->session_idr_mutex); err(); return NULL; @@ -98,12 +83,10 @@ void _ncr_sessions_item_put( struct session_item_st* item) } } -struct session_item_st* ncr_session_new(struct ncr_lists *lst_) +struct session_item_st* ncr_session_new(struct ncr_lists *lst) { - struct list_sem_st *lst; struct session_item_st* sess; - lst = &lst_->sessions; sess = kzalloc(sizeof(*sess), GFP_KERNEL); if (sess == NULL) { err(); @@ -117,23 +100,31 @@ struct session_item_st* ncr_session_new(struct ncr_lists *lst_) sizeof(struct scatterlist), GFP_KERNEL); if (sess->sg == NULL || sess->pages == NULL) { err(); - kfree(sess->sg); - kfree(sess->pages); - kfree(sess); - return NULL; + goto err_sess; } init_MUTEX(&sess->mem_mutex); atomic_set(&sess->refcnt, 1); - down(&lst->sem); - - sess->desc = _ncr_sessions_get_new_desc(lst); - list_add(&sess->list, &lst->list); - - up(&lst->sem); + mutex_lock(&lst->session_idr_mutex); + /* idr_pre_get() should preallocate enough, and, due to + session_idr_mutex, nobody else can use the preallocated data. + Therefore the loop recommended in idr_get_new() documentation is not + necessary. */ + if (idr_pre_get(&lst->session_idr, GFP_KERNEL) == 0 || + idr_get_new(&lst->session_idr, sess, &sess->desc) != 0) { + mutex_unlock(&lst->session_idr_mutex); + goto err_sess; + } + mutex_unlock(&lst->session_idr_mutex); return sess; + +err_sess: + kfree(sess->sg); + kfree(sess->pages); + kfree(sess); + return NULL; } static const struct algo_properties_st algo_properties[] = { @@ -479,25 +470,18 @@ int ret; return 0; } -static void _ncr_session_remove(struct ncr_lists *lst_, ncr_session_t desc) +static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc) { - struct list_sem_st* lst; - struct session_item_st * item, *tmp; + struct session_item_st * item; - lst = &lst_->sessions; - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - if(item->desc == desc) { - list_del(&item->list); - _ncr_sessions_item_put( item); /* decrement ref count */ - break; - } - } - - up(&lst->sem); + mutex_lock(&lst->session_idr_mutex); + item = idr_find(&lst->session_idr, desc); + if (item != NULL) + idr_remove(&lst->session_idr, desc); /* Steal the reference */ + mutex_unlock(&lst->session_idr_mutex); - return; + if (item != NULL) + _ncr_sessions_item_put(item); } static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) diff --git a/ncr.c b/ncr.c index 86571d7..6ee74d4 100644 --- a/ncr.c +++ b/ncr.c @@ -58,8 +58,8 @@ void* ncr_init_lists(void) mutex_init(&lst->key_idr_mutex); idr_init(&lst->key_idr); - init_MUTEX(&lst->sessions.sem); - INIT_LIST_HEAD(&lst->sessions.list); + mutex_init(&lst->session_idr_mutex); + idr_init(&lst->session_idr); return lst; } -- cgit From 3570fbc69b35d45ac8c57350be0d7f356aa9a7f2 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 01:50:08 +0200 Subject: Store all types of limits together. A process/user that uses one type of crypto primitive is likely to use other types as well. This saves memory and simplifies lookup in the common case. --- ncr-int.h | 1 + ncr-limits.c | 42 ++++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index ba0b69b..d8c4912 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -137,6 +137,7 @@ void _ncr_key_item_put( struct key_item_st* item); typedef enum { LIMIT_TYPE_KEY, + NUM_LIMIT_TYPES } limits_type_t; void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type); diff --git a/ncr-limits.c b/ncr-limits.c index bbcd1e9..fe61ab6 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -46,15 +46,13 @@ static unsigned int max_per_process[] = { struct limit_user_item_st { struct list_head list; uid_t uid; - limits_type_t type; - atomic_t cnt; + atomic_t cnt[NUM_LIMIT_TYPES]; }; struct limit_process_item_st { struct list_head list; pid_t pid; - limits_type_t type; - atomic_t cnt; + atomic_t cnt[NUM_LIMIT_TYPES]; }; struct limit_st { @@ -100,13 +98,14 @@ struct limit_process_item_st* pitem; struct limit_user_item_st* uitem; int add = 1; int ret; + BUG_ON(type >= NUM_LIMIT_TYPES); down(&limits.users.sem); list_for_each_entry(uitem, &limits.users.list, list) { - if (uitem->uid == uid && uitem->type == type) { + if (uitem->uid == uid) { add = 0; - if (atomic_add_unless(&uitem->cnt, 1, max_per_user[type])==0) { + if (atomic_add_unless(&uitem->cnt[type], 1, max_per_user[type])==0) { err(); up(&limits.users.sem); return -EPERM; @@ -115,6 +114,8 @@ int ret; } if (add) { + size_t i; + uitem = kmalloc( sizeof(*uitem), GFP_KERNEL); if (uitem == NULL) { err(); @@ -122,8 +123,9 @@ int ret; return -ENOMEM; } uitem->uid = uid; - uitem->type = type; - atomic_set(&uitem->cnt, 1); + for (i = 0; i < NUM_LIMIT_TYPES; i++) + atomic_set(&uitem->cnt[i], 0); + atomic_set(&uitem->cnt[type], 1); list_add(&uitem->list, &limits.users.list); } @@ -133,9 +135,9 @@ int ret; /* check process limits */ down(&limits.processes.sem); list_for_each_entry(pitem, &limits.processes.list, list) { - if (pitem->pid == pid && pitem->type == type) { + if (pitem->pid == pid) { add = 0; - if (atomic_add_unless(&pitem->cnt, 1, max_per_process[type])==0) { + if (atomic_add_unless(&pitem->cnt[type], 1, max_per_process[type])==0) { err(); up(&limits.processes.sem); @@ -147,6 +149,8 @@ int ret; if (add) { + size_t i; + pitem = kmalloc(sizeof(*pitem), GFP_KERNEL); if (uitem == NULL) { err(); @@ -155,8 +159,9 @@ int ret; goto restore_user; } pitem->pid = pid; - pitem->type = type; - atomic_set(&pitem->cnt, 1); + for (i = 0; i < NUM_LIMIT_TYPES; i++) + atomic_set(&pitem->cnt[i], 0); + atomic_set(&pitem->cnt[type], 1); list_add(&pitem->list, &limits.processes.list); } @@ -167,8 +172,8 @@ int ret; restore_user: down(&limits.users.sem); list_for_each_entry(uitem, &limits.users.list, list) { - if (uitem->uid == uid && uitem->type == type) - atomic_dec(&uitem->cnt); + if (uitem->uid == uid) + atomic_dec(&uitem->cnt[type]); } up(&limits.users.sem); return ret; @@ -179,10 +184,11 @@ void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type) struct limit_process_item_st* pitem; struct limit_user_item_st* uitem; + BUG_ON(type >= NUM_LIMIT_TYPES); down(&limits.users.sem); list_for_each_entry(uitem, &limits.users.list, list) { - if (uitem->uid == uid && uitem->type == type) { - atomic_dec(&uitem->cnt); + if (uitem->uid == uid) { + atomic_dec(&uitem->cnt[type]); } } up(&limits.users.sem); @@ -190,8 +196,8 @@ struct limit_user_item_st* uitem; /* check process limits */ down(&limits.processes.sem); list_for_each_entry(pitem, &limits.processes.list, list) { - if (pitem->pid == pid && pitem->type == type) { - atomic_dec(&pitem->cnt); + if (pitem->pid == pid) { + atomic_dec(&pitem->cnt[type]); } } up(&limits.processes.sem); -- cgit From 98402c1ba577d4fd8940d19cd4f6b79c3d105380 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 02:34:32 +0200 Subject: Use hash tables to speed up limit lookup --- ncr-limits.c | 125 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/ncr-limits.c b/ncr-limits.c index fe61ab6..3dcb9cc 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include #include #include #include @@ -44,51 +46,76 @@ static unsigned int max_per_process[] = { }; struct limit_user_item_st { - struct list_head list; + struct hlist_node hlist; uid_t uid; atomic_t cnt[NUM_LIMIT_TYPES]; }; struct limit_process_item_st { - struct list_head list; + struct hlist_node hlist; pid_t pid; atomic_t cnt[NUM_LIMIT_TYPES]; }; -struct limit_st { - struct list_sem_st users; - struct list_sem_st processes; -}; +static struct mutex user_limit_mutex; +#define USER_LIMIT_HASH_BITS 7 +#define USER_LIMIT_TABLE_SIZE (1 << USER_LIMIT_HASH_BITS) +static struct hlist_head user_limit_table[USER_LIMIT_TABLE_SIZE]; + +static struct hlist_head *user_limit_hash(uid_t uid) +{ + return &user_limit_table[hash_long(uid, USER_LIMIT_HASH_BITS)]; +} -static struct limit_st limits; +static struct mutex process_limit_mutex; +#define PROCESS_LIMIT_HASH_BITS 9 +#define PROCESS_LIMIT_TABLE_SIZE (1 << PROCESS_LIMIT_HASH_BITS) +static struct hlist_head process_limit_table[PROCESS_LIMIT_TABLE_SIZE]; + +static struct hlist_head *process_limit_hash(pid_t pid) +{ + return &process_limit_table[hash_long(pid, PROCESS_LIMIT_HASH_BITS)]; +} void ncr_limits_init(void) { - init_MUTEX(&limits.users.sem); - INIT_LIST_HEAD(&limits.users.list); + size_t i; - init_MUTEX(&limits.processes.sem); - INIT_LIST_HEAD(&limits.processes.list); + mutex_init(&user_limit_mutex); + for (i = 0; i < USER_LIMIT_TABLE_SIZE; i++) + INIT_HLIST_HEAD(&user_limit_table[i]); + + mutex_init(&process_limit_mutex); + for (i = 0; i < PROCESS_LIMIT_TABLE_SIZE; i++) + INIT_HLIST_HEAD(&process_limit_table[i]); } void ncr_limits_deinit(void) { -struct limit_process_item_st* pitem, *ptmp; -struct limit_user_item_st* uitem, *utmp; - - down(&limits.users.sem); - list_for_each_entry_safe(uitem, utmp, &limits.users.list, list) { - list_del(&uitem->list); - kfree(uitem); +struct limit_process_item_st* pitem; +struct limit_user_item_st* uitem; +struct hlist_node *pos, *tmp; +size_t i; + + mutex_lock(&user_limit_mutex); + for (i = 0; i < USER_LIMIT_TABLE_SIZE; i++) { + hlist_for_each_entry_safe(uitem, pos, tmp, &user_limit_table[i], + hlist) { + hlist_del(&uitem->hlist); + kfree(uitem); + } } - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); - down(&limits.processes.sem); - list_for_each_entry_safe(pitem, ptmp, &limits.processes.list, list) { - list_del(&pitem->list); - kfree(pitem); + mutex_lock(&process_limit_mutex); + for (i = 0; i < PROCESS_LIMIT_TABLE_SIZE; i++) { + hlist_for_each_entry_safe(pitem, pos, tmp, + &process_limit_table[i], hlist) { + hlist_del(&pitem->hlist); + kfree(pitem); + } } - up(&limits.processes.sem); + mutex_unlock(&process_limit_mutex); } @@ -96,18 +123,21 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type) { struct limit_process_item_st* pitem; struct limit_user_item_st* uitem; +struct hlist_head *user_head, *process_head; +struct hlist_node *pos; int add = 1; int ret; BUG_ON(type >= NUM_LIMIT_TYPES); - down(&limits.users.sem); - list_for_each_entry(uitem, &limits.users.list, list) { + user_head = user_limit_hash(uid); + mutex_lock(&user_limit_mutex); + hlist_for_each_entry(uitem, pos, user_head, hlist) { if (uitem->uid == uid) { add = 0; if (atomic_add_unless(&uitem->cnt[type], 1, max_per_user[type])==0) { err(); - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); return -EPERM; } } @@ -119,7 +149,7 @@ int ret; uitem = kmalloc( sizeof(*uitem), GFP_KERNEL); if (uitem == NULL) { err(); - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); return -ENOMEM; } uitem->uid = uid; @@ -127,19 +157,20 @@ int ret; atomic_set(&uitem->cnt[i], 0); atomic_set(&uitem->cnt[type], 1); - list_add(&uitem->list, &limits.users.list); + hlist_add_head(&uitem->hlist, user_head); } - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); add = 1; /* check process limits */ - down(&limits.processes.sem); - list_for_each_entry(pitem, &limits.processes.list, list) { + process_head = process_limit_hash(uid); + mutex_lock(&process_limit_mutex); + hlist_for_each_entry(pitem, pos, process_head, hlist) { if (pitem->pid == pid) { add = 0; if (atomic_add_unless(&pitem->cnt[type], 1, max_per_process[type])==0) { err(); - up(&limits.processes.sem); + mutex_unlock(&process_limit_mutex); ret = -EPERM; goto restore_user; @@ -154,7 +185,7 @@ int ret; pitem = kmalloc(sizeof(*pitem), GFP_KERNEL); if (uitem == NULL) { err(); - up(&limits.processes.sem); + mutex_unlock(&process_limit_mutex); ret = -ENOMEM; goto restore_user; } @@ -163,19 +194,19 @@ int ret; atomic_set(&pitem->cnt[i], 0); atomic_set(&pitem->cnt[type], 1); - list_add(&pitem->list, &limits.processes.list); + hlist_add_head(&pitem->hlist, process_head); } - up(&limits.processes.sem); + mutex_unlock(&process_limit_mutex); return 0; restore_user: - down(&limits.users.sem); - list_for_each_entry(uitem, &limits.users.list, list) { + mutex_lock(&user_limit_mutex); + hlist_for_each_entry(uitem, pos, user_head, hlist) { if (uitem->uid == uid) atomic_dec(&uitem->cnt[type]); } - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); return ret; } @@ -183,24 +214,28 @@ void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type) { struct limit_process_item_st* pitem; struct limit_user_item_st* uitem; +struct hlist_head *hhead; +struct hlist_node *pos; BUG_ON(type >= NUM_LIMIT_TYPES); - down(&limits.users.sem); - list_for_each_entry(uitem, &limits.users.list, list) { + hhead = user_limit_hash(uid); + mutex_lock(&user_limit_mutex); + hlist_for_each_entry(uitem, pos, hhead, hlist) { if (uitem->uid == uid) { atomic_dec(&uitem->cnt[type]); } } - up(&limits.users.sem); + mutex_unlock(&user_limit_mutex); /* check process limits */ - down(&limits.processes.sem); - list_for_each_entry(pitem, &limits.processes.list, list) { + hhead = process_limit_hash(uid); + mutex_lock(&process_limit_mutex); + hlist_for_each_entry(pitem, pos, hhead, hlist) { if (pitem->pid == pid) { atomic_dec(&pitem->cnt[type]); } } - up(&limits.processes.sem); + mutex_unlock(&process_limit_mutex); return; } -- cgit From 6c59a7213763dfe2859c7cfe6683711700fda978 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 02:36:01 +0200 Subject: Stop looking in the hash table after the first match. There should be only one entry anyway. This reduces the average lookup time when there are hash collisions roughly by half. --- ncr-limits.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ncr-limits.c b/ncr-limits.c index 3dcb9cc..4d36c4f 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -140,6 +140,7 @@ int ret; mutex_unlock(&user_limit_mutex); return -EPERM; } + break; } } @@ -175,6 +176,7 @@ int ret; ret = -EPERM; goto restore_user; } + break; } } @@ -203,8 +205,10 @@ int ret; restore_user: mutex_lock(&user_limit_mutex); hlist_for_each_entry(uitem, pos, user_head, hlist) { - if (uitem->uid == uid) + if (uitem->uid == uid) { atomic_dec(&uitem->cnt[type]); + break; + } } mutex_unlock(&user_limit_mutex); return ret; @@ -223,6 +227,7 @@ struct hlist_node *pos; hlist_for_each_entry(uitem, pos, hhead, hlist) { if (uitem->uid == uid) { atomic_dec(&uitem->cnt[type]); + break; } } mutex_unlock(&user_limit_mutex); @@ -233,6 +238,7 @@ struct hlist_node *pos; hlist_for_each_entry(pitem, pos, hhead, hlist) { if (pitem->pid == pid) { atomic_dec(&pitem->cnt[type]); + break; } } mutex_unlock(&process_limit_mutex); -- cgit From 517e0cc6199dcca54f8d20ebb90e304d4cc93c43 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 28 Jul 2010 02:40:53 +0200 Subject: Finally remove the unused list_sem_st. --- ncr-int.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 9b66cbd..f6d394a 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -88,11 +88,6 @@ struct key_item_st { ncr_key_t desc; }; -struct list_sem_st { - struct list_head list; - struct semaphore sem; -}; - /* all the data associated with the open descriptor * are here. */ -- cgit