@@ -81,16 +81,35 @@ static void crypto_destroy_instance(struct crypto_alg *alg)
8181 crypto_tmpl_put (tmpl );
8282}
8383
84+ static struct list_head * crypto_more_spawns (struct crypto_alg * alg ,
85+ struct list_head * stack ,
86+ struct list_head * top ,
87+ struct list_head * secondary_spawns )
88+ {
89+ struct crypto_spawn * spawn , * n ;
90+
91+ if (list_empty (stack ))
92+ return NULL ;
93+
94+ spawn = list_first_entry (stack , struct crypto_spawn , list );
95+ n = list_entry (spawn -> list .next , struct crypto_spawn , list );
96+
97+ if (spawn -> alg && & n -> list != stack && !n -> alg )
98+ n -> alg = (n -> list .next == stack ) ? alg :
99+ & list_entry (n -> list .next , struct crypto_spawn ,
100+ list )-> inst -> alg ;
101+
102+ list_move (& spawn -> list , secondary_spawns );
103+
104+ return & n -> list == stack ? top : & n -> inst -> alg .cra_users ;
105+ }
106+
84107static void crypto_remove_spawn (struct crypto_spawn * spawn ,
85- struct list_head * list ,
86- struct list_head * secondary_spawns )
108+ struct list_head * list )
87109{
88110 struct crypto_instance * inst = spawn -> inst ;
89111 struct crypto_template * tmpl = inst -> tmpl ;
90112
91- list_del_init (& spawn -> list );
92- spawn -> alg = NULL ;
93-
94113 if (crypto_is_dead (& inst -> alg ))
95114 return ;
96115
@@ -106,25 +125,55 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn,
106125 hlist_del (& inst -> list );
107126 inst -> alg .cra_destroy = crypto_destroy_instance ;
108127
109- list_splice ( & inst -> alg .cra_users , secondary_spawns );
128+ BUG_ON (! list_empty ( & inst -> alg .cra_users ) );
110129}
111130
112- static void crypto_remove_spawns (struct list_head * spawns ,
113- struct list_head * list , u32 new_type )
131+ static void crypto_remove_spawns (struct crypto_alg * alg ,
132+ struct list_head * list ,
133+ struct crypto_alg * nalg )
114134{
135+ u32 new_type = (nalg ?: alg )-> cra_flags ;
115136 struct crypto_spawn * spawn , * n ;
116137 LIST_HEAD (secondary_spawns );
138+ struct list_head * spawns ;
139+ LIST_HEAD (stack );
140+ LIST_HEAD (top );
117141
142+ spawns = & alg -> cra_users ;
118143 list_for_each_entry_safe (spawn , n , spawns , list ) {
119144 if ((spawn -> alg -> cra_flags ^ new_type ) & spawn -> mask )
120145 continue ;
121146
122- crypto_remove_spawn ( spawn , list , & secondary_spawns );
147+ list_move ( & spawn -> list , & top );
123148 }
124149
125- while (!list_empty (& secondary_spawns )) {
126- list_for_each_entry_safe (spawn , n , & secondary_spawns , list )
127- crypto_remove_spawn (spawn , list , & secondary_spawns );
150+ spawns = & top ;
151+ do {
152+ while (!list_empty (spawns )) {
153+ struct crypto_instance * inst ;
154+
155+ spawn = list_first_entry (spawns , struct crypto_spawn ,
156+ list );
157+ inst = spawn -> inst ;
158+
159+ BUG_ON (& inst -> alg == alg );
160+
161+ list_move (& spawn -> list , & stack );
162+
163+ if (& inst -> alg == nalg )
164+ break ;
165+
166+ spawn -> alg = NULL ;
167+ spawns = & inst -> alg .cra_users ;
168+ }
169+ } while ((spawns = crypto_more_spawns (alg , & stack , & top ,
170+ & secondary_spawns )));
171+
172+ list_for_each_entry_safe (spawn , n , & secondary_spawns , list ) {
173+ if (spawn -> alg )
174+ list_move (& spawn -> list , & spawn -> alg -> cra_users );
175+ else
176+ crypto_remove_spawn (spawn , list );
128177 }
129178}
130179
@@ -258,7 +307,7 @@ void crypto_alg_tested(const char *name, int err)
258307 q -> cra_priority > alg -> cra_priority )
259308 continue ;
260309
261- crypto_remove_spawns (& q -> cra_users , & list , alg -> cra_flags );
310+ crypto_remove_spawns (q , & list , alg );
262311 }
263312
264313complete :
@@ -330,7 +379,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
330379
331380 crypto_notify (CRYPTO_MSG_ALG_UNREGISTER , alg );
332381 list_del_init (& alg -> cra_list );
333- crypto_remove_spawns (& alg -> cra_users , list , alg -> cra_flags );
382+ crypto_remove_spawns (alg , list , NULL );
334383
335384 return 0 ;
336385}
0 commit comments