@@ -713,13 +713,14 @@ static void check_lifetime(struct work_struct *work)
713713
714714 rcu_read_lock ();
715715 hlist_for_each_entry_rcu (ifa , & inet_addr_lst [i ], hash ) {
716- unsigned long age ;
716+ unsigned long age , tstamp ;
717717
718718 if (ifa -> ifa_flags & IFA_F_PERMANENT )
719719 continue ;
720720
721+ tstamp = READ_ONCE (ifa -> ifa_tstamp );
721722 /* We try to batch several events at once. */
722- age = (now - ifa -> ifa_tstamp +
723+ age = (now - tstamp +
723724 ADDRCONF_TIMER_FUZZ_MINUS ) / HZ ;
724725
725726 if (ifa -> ifa_valid_lft != INFINITY_LIFE_TIME &&
@@ -729,17 +730,17 @@ static void check_lifetime(struct work_struct *work)
729730 INFINITY_LIFE_TIME ) {
730731 continue ;
731732 } else if (age >= ifa -> ifa_preferred_lft ) {
732- if (time_before (ifa -> ifa_tstamp +
733+ if (time_before (tstamp +
733734 ifa -> ifa_valid_lft * HZ , next ))
734- next = ifa -> ifa_tstamp +
735+ next = tstamp +
735736 ifa -> ifa_valid_lft * HZ ;
736737
737738 if (!(ifa -> ifa_flags & IFA_F_DEPRECATED ))
738739 change_needed = true;
739- } else if (time_before (ifa -> ifa_tstamp +
740+ } else if (time_before (tstamp +
740741 ifa -> ifa_preferred_lft * HZ ,
741742 next )) {
742- next = ifa -> ifa_tstamp +
743+ next = tstamp +
743744 ifa -> ifa_preferred_lft * HZ ;
744745 }
745746 }
@@ -819,9 +820,9 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
819820 ifa -> ifa_flags |= IFA_F_DEPRECATED ;
820821 ifa -> ifa_preferred_lft = timeout ;
821822 }
822- ifa -> ifa_tstamp = jiffies ;
823+ WRITE_ONCE ( ifa -> ifa_tstamp , jiffies ) ;
823824 if (!ifa -> ifa_cstamp )
824- ifa -> ifa_cstamp = ifa -> ifa_tstamp ;
825+ WRITE_ONCE ( ifa -> ifa_cstamp , ifa -> ifa_tstamp ) ;
825826}
826827
827828static struct in_ifaddr * rtm_to_ifaddr (struct net * net , struct nlmsghdr * nlh ,
@@ -1676,6 +1677,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
16761677{
16771678 struct ifaddrmsg * ifm ;
16781679 struct nlmsghdr * nlh ;
1680+ unsigned long tstamp ;
16791681 u32 preferred , valid ;
16801682
16811683 nlh = nlmsg_put (skb , args -> portid , args -> seq , args -> event , sizeof (* ifm ),
@@ -1694,11 +1696,12 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
16941696 nla_put_s32 (skb , IFA_TARGET_NETNSID , args -> netnsid ))
16951697 goto nla_put_failure ;
16961698
1699+ tstamp = READ_ONCE (ifa -> ifa_tstamp );
16971700 if (!(ifm -> ifa_flags & IFA_F_PERMANENT )) {
16981701 preferred = ifa -> ifa_preferred_lft ;
16991702 valid = ifa -> ifa_valid_lft ;
17001703 if (preferred != INFINITY_LIFE_TIME ) {
1701- long tval = (jiffies - ifa -> ifa_tstamp ) / HZ ;
1704+ long tval = (jiffies - tstamp ) / HZ ;
17021705
17031706 if (preferred > tval )
17041707 preferred -= tval ;
@@ -1728,7 +1731,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
17281731 nla_put_u32 (skb , IFA_FLAGS , ifa -> ifa_flags ) ||
17291732 (ifa -> ifa_rt_priority &&
17301733 nla_put_u32 (skb , IFA_RT_PRIORITY , ifa -> ifa_rt_priority )) ||
1731- put_cacheinfo (skb , ifa -> ifa_cstamp , ifa -> ifa_tstamp ,
1734+ put_cacheinfo (skb , READ_ONCE ( ifa -> ifa_cstamp ), tstamp ,
17321735 preferred , valid ))
17331736 goto nla_put_failure ;
17341737
0 commit comments