summaryrefslogtreecommitdiffstats
path: root/crypto/userspace/ncr-sessions.c
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-07-31 00:53:54 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-07-31 00:53:54 +0200
commit2bc2319cbe2ec8ead62b816cc15ed155486f0ae0 (patch)
tree3c2336749da4cbb881ebe56903f9f026e17b4a4e /crypto/userspace/ncr-sessions.c
parent682bdfb751e081a6633c78a2cf20e2d81a2ca03c (diff)
parent49d7012c4c62f6681378a56d9af4d721178b8ad3 (diff)
downloadkernel-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.c129
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;