@@ -90,7 +90,7 @@ struct dsthash_ent {
9090
9191struct xt_hashlimit_htable {
9292 struct hlist_node node ; /* global list of all htables */
93- atomic_t use ;
93+ int use ;
9494 u_int8_t family ;
9595 bool rnd_initialized ;
9696
@@ -109,8 +109,7 @@ struct xt_hashlimit_htable {
109109 struct hlist_head hash [0 ]; /* hashtable itself */
110110};
111111
112- static DEFINE_SPINLOCK (hashlimit_lock ); /* protects htables list */
113- static DEFINE_MUTEX (hlimit_mutex ); /* additional checkentry protection */
112+ static DEFINE_MUTEX (hashlimit_mutex ); /* protects htables list */
114113static struct kmem_cache * hashlimit_cachep __read_mostly ;
115114
116115static inline bool dst_cmp (const struct dsthash_ent * ent ,
@@ -244,7 +243,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_
244243 for (i = 0 ; i < hinfo -> cfg .size ; i ++ )
245244 INIT_HLIST_HEAD (& hinfo -> hash [i ]);
246245
247- atomic_set ( & hinfo -> use , 1 ) ;
246+ hinfo -> use = 1 ;
248247 hinfo -> count = 0 ;
249248 hinfo -> family = family ;
250249 hinfo -> rnd_initialized = false;
@@ -263,9 +262,9 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_
263262 hinfo -> timer .expires = jiffies + msecs_to_jiffies (hinfo -> cfg .gc_interval );
264263 add_timer (& hinfo -> timer );
265264
266- spin_lock_bh ( & hashlimit_lock );
265+ mutex_lock ( & hashlimit_mutex );
267266 hlist_add_head (& hinfo -> node , & hashlimit_net -> htables );
268- spin_unlock_bh ( & hashlimit_lock );
267+ mutex_unlock ( & hashlimit_mutex );
269268
270269 return 0 ;
271270}
@@ -308,7 +307,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
308307 for (i = 0 ; i < hinfo -> cfg .size ; i ++ )
309308 INIT_HLIST_HEAD (& hinfo -> hash [i ]);
310309
311- atomic_set ( & hinfo -> use , 1 ) ;
310+ hinfo -> use = 1 ;
312311 hinfo -> count = 0 ;
313312 hinfo -> family = family ;
314313 hinfo -> rnd_initialized = false;
@@ -328,9 +327,9 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
328327 hinfo -> timer .expires = jiffies + msecs_to_jiffies (hinfo -> cfg .gc_interval );
329328 add_timer (& hinfo -> timer );
330329
331- spin_lock_bh ( & hashlimit_lock );
330+ mutex_lock ( & hashlimit_mutex );
332331 hlist_add_head (& hinfo -> node , & hashlimit_net -> htables );
333- spin_unlock_bh ( & hashlimit_lock );
332+ mutex_unlock ( & hashlimit_mutex );
334333
335334 return 0 ;
336335}
@@ -402,27 +401,24 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
402401 struct xt_hashlimit_htable * hinfo ;
403402 struct hlist_node * pos ;
404403
405- spin_lock_bh (& hashlimit_lock );
406404 hlist_for_each_entry (hinfo , pos , & hashlimit_net -> htables , node ) {
407405 if (!strcmp (name , hinfo -> pde -> name ) &&
408406 hinfo -> family == family ) {
409- atomic_inc (& hinfo -> use );
410- spin_unlock_bh (& hashlimit_lock );
407+ hinfo -> use ++ ;
411408 return hinfo ;
412409 }
413410 }
414- spin_unlock_bh (& hashlimit_lock );
415411 return NULL ;
416412}
417413
418414static void htable_put (struct xt_hashlimit_htable * hinfo )
419415{
420- if ( atomic_dec_and_test ( & hinfo -> use )) {
421- spin_lock_bh ( & hashlimit_lock );
416+ mutex_lock ( & hashlimit_mutex );
417+ if ( -- hinfo -> use == 0 ) {
422418 hlist_del (& hinfo -> node );
423- spin_unlock_bh (& hashlimit_lock );
424419 htable_destroy (hinfo );
425420 }
421+ mutex_unlock (& hashlimit_mutex );
426422}
427423
428424/* The algorithm used is the Simple Token Bucket Filter (TBF)
@@ -710,19 +706,13 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
710706 if (r -> name [sizeof (r -> name ) - 1 ] != '\0' )
711707 return false;
712708
713- /* This is the best we've got: We cannot release and re-grab lock,
714- * since checkentry() is called before x_tables.c grabs xt_mutex.
715- * We also cannot grab the hashtable spinlock, since htable_create will
716- * call vmalloc, and that can sleep. And we cannot just re-search
717- * the list of htable's in htable_create(), since then we would
718- * create duplicate proc files. -HW */
719- mutex_lock (& hlimit_mutex );
709+ mutex_lock (& hashlimit_mutex );
720710 r -> hinfo = htable_find_get (net , r -> name , par -> match -> family );
721711 if (!r -> hinfo && htable_create_v0 (net , r , par -> match -> family ) != 0 ) {
722- mutex_unlock (& hlimit_mutex );
712+ mutex_unlock (& hashlimit_mutex );
723713 return false;
724714 }
725- mutex_unlock (& hlimit_mutex );
715+ mutex_unlock (& hashlimit_mutex );
726716
727717 return true;
728718}
@@ -752,19 +742,13 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
752742 return false;
753743 }
754744
755- /* This is the best we've got: We cannot release and re-grab lock,
756- * since checkentry() is called before x_tables.c grabs xt_mutex.
757- * We also cannot grab the hashtable spinlock, since htable_create will
758- * call vmalloc, and that can sleep. And we cannot just re-search
759- * the list of htable's in htable_create(), since then we would
760- * create duplicate proc files. -HW */
761- mutex_lock (& hlimit_mutex );
745+ mutex_lock (& hashlimit_mutex );
762746 info -> hinfo = htable_find_get (net , info -> name , par -> match -> family );
763747 if (!info -> hinfo && htable_create (net , info , par -> match -> family ) != 0 ) {
764- mutex_unlock (& hlimit_mutex );
748+ mutex_unlock (& hashlimit_mutex );
765749 return false;
766750 }
767- mutex_unlock (& hlimit_mutex );
751+ mutex_unlock (& hashlimit_mutex );
768752 return true;
769753}
770754
0 commit comments