diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-07-31 00:53:54 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-07-31 00:53:54 +0200 |
commit | 2bc2319cbe2ec8ead62b816cc15ed155486f0ae0 (patch) | |
tree | 3c2336749da4cbb881ebe56903f9f026e17b4a4e /crypto/userspace/ncr-sessions.c | |
parent | 682bdfb751e081a6633c78a2cf20e2d81a2ca03c (diff) | |
parent | 49d7012c4c62f6681378a56d9af4d721178b8ad3 (diff) | |
download | kernel-crypto-2bc2319cbe2ec8ead62b816cc15ed155486f0ae0.tar.gz kernel-crypto-2bc2319cbe2ec8ead62b816cc15ed155486f0ae0.tar.xz kernel-crypto-2bc2319cbe2ec8ead62b816cc15ed155486f0ae0.zip |
Merge branch 'standalone-rename' into userspace-crypto
Conflicts:
crypto/userspace/ncr-int.h
crypto/userspace/ncr-limits.c
Diffstat (limited to 'crypto/userspace/ncr-sessions.c')
-rw-r--r-- | crypto/userspace/ncr-sessions.c | 129 |
1 files changed, 59 insertions, 70 deletions
diff --git a/crypto/userspace/ncr-sessions.c b/crypto/userspace/ncr-sessions.c index 8dcc7d8abb4..8052ba6123f 100644 --- a/crypto/userspace/ncr-sessions.c +++ b/crypto/userspace/ncr-sessions.c @@ -31,53 +31,39 @@ #include <linux/scatterlist.h> 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) +static int session_list_deinit_fn(int id, void *item, void *unused) { - if(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); - - } + (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 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 session_item_st* item; - 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; @@ -97,7 +83,7 @@ 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 session_item_st* sess; @@ -114,23 +100,31 @@ struct session_item_st* ncr_session_new(struct list_sem_st* 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, 2); /* One for lst->list, one for "sess" */ - 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[] = { @@ -226,7 +220,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 -ENOMEM; @@ -250,7 +244,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; @@ -319,7 +313,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; @@ -390,7 +384,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); } _ncr_sessions_item_put(ns); @@ -416,7 +410,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; @@ -479,23 +473,18 @@ 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 session_item_st * item, *tmp; + struct session_item_st * item; - 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) @@ -630,7 +619,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; @@ -750,7 +739,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; @@ -900,7 +889,7 @@ fail: } _ncr_sessions_item_put(sess); - _ncr_session_remove(&lists->sessions, op->ses); + _ncr_session_remove(lists, op->ses); return ret; } @@ -913,14 +902,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; |