diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/algapi.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c index 1c2185b5b005..f137a432061f 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c | |||
@@ -84,36 +84,47 @@ static void crypto_destroy_instance(struct crypto_alg *alg) | |||
84 | crypto_tmpl_put(tmpl); | 84 | crypto_tmpl_put(tmpl); |
85 | } | 85 | } |
86 | 86 | ||
87 | static void crypto_remove_spawns(struct list_head *spawns, | 87 | static void crypto_remove_spawn(struct crypto_spawn *spawn, |
88 | struct list_head *list) | 88 | struct list_head *list, |
89 | struct list_head *secondary_spawns) | ||
89 | { | 90 | { |
90 | struct crypto_spawn *spawn, *n; | 91 | struct crypto_instance *inst = spawn->inst; |
92 | struct crypto_template *tmpl = inst->tmpl; | ||
91 | 93 | ||
92 | list_for_each_entry_safe(spawn, n, spawns, list) { | 94 | list_del_init(&spawn->list); |
93 | struct crypto_instance *inst = spawn->inst; | 95 | spawn->alg = NULL; |
94 | struct crypto_template *tmpl = inst->tmpl; | ||
95 | 96 | ||
96 | list_del_init(&spawn->list); | 97 | if (crypto_is_dead(&inst->alg)) |
97 | spawn->alg = NULL; | 98 | return; |
98 | 99 | ||
99 | if (crypto_is_dead(&inst->alg)) | 100 | inst->alg.cra_flags |= CRYPTO_ALG_DEAD; |
100 | continue; | 101 | if (!tmpl || !crypto_tmpl_get(tmpl)) |
102 | return; | ||
103 | |||
104 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); | ||
105 | list_move(&inst->alg.cra_list, list); | ||
106 | hlist_del(&inst->list); | ||
107 | inst->alg.cra_destroy = crypto_destroy_instance; | ||
108 | |||
109 | list_splice(&inst->alg.cra_users, secondary_spawns); | ||
110 | } | ||
111 | |||
112 | static void crypto_remove_spawns(struct list_head *spawns, | ||
113 | struct list_head *list, u32 new_type) | ||
114 | { | ||
115 | struct crypto_spawn *spawn, *n; | ||
116 | LIST_HEAD(secondary_spawns); | ||
101 | 117 | ||
102 | inst->alg.cra_flags |= CRYPTO_ALG_DEAD; | 118 | list_for_each_entry_safe(spawn, n, spawns, list) { |
103 | if (!tmpl || !crypto_tmpl_get(tmpl)) | 119 | if ((spawn->alg->cra_flags ^ new_type) & spawn->mask) |
104 | continue; | 120 | continue; |
105 | 121 | ||
106 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); | 122 | crypto_remove_spawn(spawn, list, &secondary_spawns); |
107 | list_move(&inst->alg.cra_list, list); | 123 | } |
108 | hlist_del(&inst->list); | ||
109 | inst->alg.cra_destroy = crypto_destroy_instance; | ||
110 | 124 | ||
111 | if (!list_empty(&inst->alg.cra_users)) { | 125 | while (!list_empty(&secondary_spawns)) { |
112 | if (&n->list == spawns) | 126 | list_for_each_entry_safe(spawn, n, &secondary_spawns, list) |
113 | n = list_entry(inst->alg.cra_users.next, | 127 | crypto_remove_spawn(spawn, list, &secondary_spawns); |
114 | typeof(*n), list); | ||
115 | __list_splice(&inst->alg.cra_users, spawns->prev); | ||
116 | } | ||
117 | } | 128 | } |
118 | } | 129 | } |
119 | 130 | ||
@@ -164,7 +175,7 @@ static int __crypto_register_alg(struct crypto_alg *alg, | |||
164 | q->cra_priority > alg->cra_priority) | 175 | q->cra_priority > alg->cra_priority) |
165 | continue; | 176 | continue; |
166 | 177 | ||
167 | crypto_remove_spawns(&q->cra_users, list); | 178 | crypto_remove_spawns(&q->cra_users, list, alg->cra_flags); |
168 | } | 179 | } |
169 | 180 | ||
170 | list_add(&alg->cra_list, &crypto_alg_list); | 181 | list_add(&alg->cra_list, &crypto_alg_list); |
@@ -214,7 +225,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) | |||
214 | 225 | ||
215 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); | 226 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); |
216 | list_del_init(&alg->cra_list); | 227 | list_del_init(&alg->cra_list); |
217 | crypto_remove_spawns(&alg->cra_users, list); | 228 | crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags); |
218 | 229 | ||
219 | return 0; | 230 | return 0; |
220 | } | 231 | } |
@@ -351,11 +362,12 @@ err: | |||
351 | EXPORT_SYMBOL_GPL(crypto_register_instance); | 362 | EXPORT_SYMBOL_GPL(crypto_register_instance); |
352 | 363 | ||
353 | int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, | 364 | int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, |
354 | struct crypto_instance *inst) | 365 | struct crypto_instance *inst, u32 mask) |
355 | { | 366 | { |
356 | int err = -EAGAIN; | 367 | int err = -EAGAIN; |
357 | 368 | ||
358 | spawn->inst = inst; | 369 | spawn->inst = inst; |
370 | spawn->mask = mask; | ||
359 | 371 | ||
360 | down_write(&crypto_alg_sem); | 372 | down_write(&crypto_alg_sem); |
361 | if (!crypto_is_moribund(alg)) { | 373 | if (!crypto_is_moribund(alg)) { |
@@ -494,7 +506,8 @@ struct crypto_instance *crypto_alloc_instance(const char *name, | |||
494 | goto err_free_inst; | 506 | goto err_free_inst; |
495 | 507 | ||
496 | spawn = crypto_instance_ctx(inst); | 508 | spawn = crypto_instance_ctx(inst); |
497 | err = crypto_init_spawn(spawn, alg, inst); | 509 | err = crypto_init_spawn(spawn, alg, inst, |
510 | CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); | ||
498 | 511 | ||
499 | if (err) | 512 | if (err) |
500 | goto err_free_inst; | 513 | goto err_free_inst; |