@@ -608,6 +608,7 @@ static void sfq_perturbation(struct timer_list *t)
608608 struct Qdisc * sch = q -> sch ;
609609 spinlock_t * root_lock ;
610610 siphash_key_t nkey ;
611+ int period ;
611612
612613 get_random_bytes (& nkey , sizeof (nkey ));
613614 rcu_read_lock ();
@@ -618,8 +619,12 @@ static void sfq_perturbation(struct timer_list *t)
618619 sfq_rehash (sch );
619620 spin_unlock (root_lock );
620621
621- if (q -> perturb_period )
622- mod_timer (& q -> perturb_timer , jiffies + q -> perturb_period );
622+ /* q->perturb_period can change under us from
623+ * sfq_change() and sfq_destroy().
624+ */
625+ period = READ_ONCE (q -> perturb_period );
626+ if (period )
627+ mod_timer (& q -> perturb_timer , jiffies + period );
623628 rcu_read_unlock ();
624629}
625630
@@ -662,7 +667,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
662667 q -> quantum = ctl -> quantum ;
663668 q -> scaled_quantum = SFQ_ALLOT_SIZE (q -> quantum );
664669 }
665- q -> perturb_period = ctl -> perturb_period * HZ ;
670+ WRITE_ONCE ( q -> perturb_period , ctl -> perturb_period * HZ ) ;
666671 if (ctl -> flows )
667672 q -> maxflows = min_t (u32 , ctl -> flows , SFQ_MAX_FLOWS );
668673 if (ctl -> divisor ) {
@@ -724,7 +729,7 @@ static void sfq_destroy(struct Qdisc *sch)
724729 struct sfq_sched_data * q = qdisc_priv (sch );
725730
726731 tcf_block_put (q -> block );
727- q -> perturb_period = 0 ;
732+ WRITE_ONCE ( q -> perturb_period , 0 ) ;
728733 del_timer_sync (& q -> perturb_timer );
729734 sfq_free (q -> ht );
730735 sfq_free (q -> slots );
0 commit comments