@@ -373,8 +373,9 @@ static void
373373mtype_ext_cleanup (struct ip_set * set , struct hbucket * n )
374374{
375375 int i ;
376+ u8 pos = smp_load_acquire (& n -> pos );
376377
377- for (i = 0 ; i < n -> pos ; i ++ )
378+ for (i = 0 ; i < pos ; i ++ )
378379 if (test_bit (i , n -> used ))
379380 ip_set_ext_destroy (set , ahash_data (n , i , set -> dsize ));
380381}
@@ -477,15 +478,16 @@ mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r)
477478#ifdef IP_SET_HASH_WITH_NETS
478479 u8 k ;
479480#endif
480- u8 htable_bits = t -> htable_bits ;
481+ u8 pos , htable_bits = t -> htable_bits ;
481482
482483 spin_lock_bh (& t -> hregion [r ].lock );
483484 for (i = ahash_bucket_start (r , htable_bits );
484485 i < ahash_bucket_end (r , htable_bits ); i ++ ) {
485486 n = __ipset_dereference (hbucket (t , i ));
486487 if (!n )
487488 continue ;
488- for (j = 0 , d = 0 ; j < n -> pos ; j ++ ) {
489+ pos = smp_load_acquire (& n -> pos );
490+ for (j = 0 , d = 0 ; j < pos ; j ++ ) {
489491 if (!test_bit (j , n -> used )) {
490492 d ++ ;
491493 continue ;
@@ -521,7 +523,7 @@ mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r)
521523 /* Still try to delete expired elements. */
522524 continue ;
523525 tmp -> size = n -> size - AHASH_INIT_SIZE ;
524- for (j = 0 , d = 0 ; j < n -> pos ; j ++ ) {
526+ for (j = 0 , d = 0 ; j < pos ; j ++ ) {
525527 if (!test_bit (j , n -> used ))
526528 continue ;
527529 data = ahash_data (n , j , dsize );
@@ -610,7 +612,7 @@ mtype_resize(struct ip_set *set, bool retried)
610612{
611613 struct htype * h = set -> data ;
612614 struct htable * t , * orig ;
613- u8 htable_bits ;
615+ u8 pos , htable_bits ;
614616 size_t hsize , dsize = set -> dsize ;
615617#ifdef IP_SET_HASH_WITH_NETS
616618 u8 flags ;
@@ -672,7 +674,8 @@ mtype_resize(struct ip_set *set, bool retried)
672674 n = __ipset_dereference (hbucket (orig , i ));
673675 if (!n )
674676 continue ;
675- for (j = 0 ; j < n -> pos ; j ++ ) {
677+ pos = smp_load_acquire (& n -> pos );
678+ for (j = 0 ; j < pos ; j ++ ) {
676679 if (!test_bit (j , n -> used ))
677680 continue ;
678681 data = ahash_data (n , j , dsize );
@@ -796,9 +799,10 @@ mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
796799{
797800 struct htype * h = set -> data ;
798801 const struct htable * t ;
799- u32 i , j , r ;
800802 struct hbucket * n ;
801803 struct mtype_elem * data ;
804+ u32 i , j , r ;
805+ u8 pos ;
802806
803807 t = rcu_dereference_bh (h -> table );
804808 for (r = 0 ; r < ahash_numof_locks (t -> htable_bits ); r ++ ) {
@@ -807,7 +811,8 @@ mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
807811 n = rcu_dereference_bh (hbucket (t , i ));
808812 if (!n )
809813 continue ;
810- for (j = 0 ; j < n -> pos ; j ++ ) {
814+ pos = smp_load_acquire (& n -> pos );
815+ for (j = 0 ; j < pos ; j ++ ) {
811816 if (!test_bit (j , n -> used ))
812817 continue ;
813818 data = ahash_data (n , j , set -> dsize );
@@ -831,10 +836,11 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
831836 const struct mtype_elem * d = value ;
832837 struct mtype_elem * data ;
833838 struct hbucket * n , * old = ERR_PTR (- ENOENT );
834- int i , j = -1 , npos = 0 , ret ;
839+ int i , j = -1 , ret ;
835840 bool flag_exist = flags & IPSET_FLAG_EXIST ;
836841 bool deleted = false, forceadd = false, reuse = false;
837842 u32 r , key , multi = 0 , elements , maxelem ;
843+ u8 npos = 0 ;
838844
839845 rcu_read_lock_bh ();
840846 t = rcu_dereference_bh (h -> table );
@@ -876,8 +882,8 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
876882 ext_size (AHASH_INIT_SIZE , set -> dsize );
877883 goto copy_elem ;
878884 }
879- npos = n -> pos ;
880- for (i = 0 ; i < n -> pos ; i ++ ) {
885+ npos = smp_load_acquire ( & n -> pos ) ;
886+ for (i = 0 ; i < npos ; i ++ ) {
881887 if (!test_bit (i , n -> used )) {
882888 /* Reuse first deleted entry */
883889 if (j == -1 ) {
@@ -921,7 +927,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
921927 if (elements >= maxelem )
922928 goto set_full ;
923929 /* Create a new slot */
924- if (n -> pos >= n -> size ) {
930+ if (npos >= n -> size ) {
925931#ifdef IP_SET_HASH_WITH_MULTI
926932 if (h -> bucketsize >= AHASH_MAX_TUNED )
927933 goto set_full ;
@@ -950,8 +956,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
950956 }
951957
952958copy_elem :
953- j = npos ;
954- npos = n -> pos + 1 ;
959+ j = npos ++ ;
955960 data = ahash_data (n , j , set -> dsize );
956961copy_data :
957962 t -> hregion [r ].elements ++ ;
@@ -974,7 +979,8 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
974979 if (SET_WITH_TIMEOUT (set ))
975980 ip_set_timeout_set (ext_timeout (data , set ), ext -> timeout );
976981 smp_mb__before_atomic ();
977- n -> pos = npos ;
982+ /* Ensure all data writes are visible before updating position */
983+ smp_store_release (& n -> pos , npos );
978984 set_bit (j , n -> used );
979985 if (old != ERR_PTR (- ENOENT )) {
980986 rcu_assign_pointer (hbucket (t , key ), n );
@@ -1033,6 +1039,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10331039 int i , j , k , r , ret = - IPSET_ERR_EXIST ;
10341040 u32 key , multi = 0 ;
10351041 size_t dsize = set -> dsize ;
1042+ u8 pos ;
10361043
10371044 /* Userspace add and resize is excluded by the mutex.
10381045 * Kernespace add does not trigger resize.
@@ -1048,7 +1055,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10481055 n = rcu_dereference_bh (hbucket (t , key ));
10491056 if (!n )
10501057 goto out ;
1051- for (i = 0 , k = 0 ; i < n -> pos ; i ++ ) {
1058+ pos = smp_load_acquire (& n -> pos );
1059+ for (i = 0 , k = 0 ; i < pos ; i ++ ) {
10521060 if (!test_bit (i , n -> used )) {
10531061 k ++ ;
10541062 continue ;
@@ -1062,8 +1070,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10621070 ret = 0 ;
10631071 clear_bit (i , n -> used );
10641072 smp_mb__after_atomic ();
1065- if (i + 1 == n -> pos )
1066- n -> pos -- ;
1073+ if (i + 1 == pos )
1074+ smp_store_release ( & n -> pos , -- pos ) ;
10671075 t -> hregion [r ].elements -- ;
10681076#ifdef IP_SET_HASH_WITH_NETS
10691077 for (j = 0 ; j < IPSET_NET_COUNT ; j ++ )
@@ -1085,11 +1093,11 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10851093 x -> flags = flags ;
10861094 }
10871095 }
1088- for (; i < n -> pos ; i ++ ) {
1096+ for (; i < pos ; i ++ ) {
10891097 if (!test_bit (i , n -> used ))
10901098 k ++ ;
10911099 }
1092- if (k == n -> pos ) {
1100+ if (k == pos ) {
10931101 t -> hregion [r ].ext_size -= ext_size (n -> size , dsize );
10941102 rcu_assign_pointer (hbucket (t , key ), NULL );
10951103 kfree_rcu (n , rcu );
@@ -1100,7 +1108,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
11001108 if (!tmp )
11011109 goto out ;
11021110 tmp -> size = n -> size - AHASH_INIT_SIZE ;
1103- for (j = 0 , k = 0 ; j < n -> pos ; j ++ ) {
1111+ for (j = 0 , k = 0 ; j < pos ; j ++ ) {
11041112 if (!test_bit (j , n -> used ))
11051113 continue ;
11061114 data = ahash_data (n , j , dsize );
@@ -1161,6 +1169,7 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
11611169 int ret , i , j = 0 ;
11621170#endif
11631171 u32 key , multi = 0 ;
1172+ u8 pos ;
11641173
11651174 pr_debug ("test by nets\n" );
11661175 for (; j < NLEN && h -> nets [j ].cidr [0 ] && !multi ; j ++ ) {
@@ -1178,7 +1187,8 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
11781187 n = rcu_dereference_bh (hbucket (t , key ));
11791188 if (!n )
11801189 continue ;
1181- for (i = 0 ; i < n -> pos ; i ++ ) {
1190+ pos = smp_load_acquire (& n -> pos );
1191+ for (i = 0 ; i < pos ; i ++ ) {
11821192 if (!test_bit (i , n -> used ))
11831193 continue ;
11841194 data = ahash_data (n , i , set -> dsize );
@@ -1212,6 +1222,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
12121222 struct mtype_elem * data ;
12131223 int i , ret = 0 ;
12141224 u32 key , multi = 0 ;
1225+ u8 pos ;
12151226
12161227 rcu_read_lock_bh ();
12171228 t = rcu_dereference_bh (h -> table );
@@ -1234,7 +1245,8 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
12341245 ret = 0 ;
12351246 goto out ;
12361247 }
1237- for (i = 0 ; i < n -> pos ; i ++ ) {
1248+ pos = smp_load_acquire (& n -> pos );
1249+ for (i = 0 ; i < pos ; i ++ ) {
12381250 if (!test_bit (i , n -> used ))
12391251 continue ;
12401252 data = ahash_data (n , i , set -> dsize );
@@ -1339,6 +1351,7 @@ mtype_list(const struct ip_set *set,
13391351 /* We assume that one hash bucket fills into one page */
13401352 void * incomplete ;
13411353 int i , ret = 0 ;
1354+ u8 pos ;
13421355
13431356 atd = nla_nest_start (skb , IPSET_ATTR_ADT );
13441357 if (!atd )
@@ -1357,7 +1370,8 @@ mtype_list(const struct ip_set *set,
13571370 cb -> args [IPSET_CB_ARG0 ], t , n );
13581371 if (!n )
13591372 continue ;
1360- for (i = 0 ; i < n -> pos ; i ++ ) {
1373+ pos = smp_load_acquire (& n -> pos );
1374+ for (i = 0 ; i < pos ; i ++ ) {
13611375 if (!test_bit (i , n -> used ))
13621376 continue ;
13631377 e = ahash_data (n , i , set -> dsize );
0 commit comments