} rxopt;
 
        /* sockopt flags */
-       __u8                    srcprefs:3;     /* 001: prefer temporary address
+       __u8                    srcprefs;       /* 001: prefer temporary address
                                                 * 010: prefer public address
                                                 * 100: prefer care-of address
                                                 */
 
  */
 static inline int rt6_srcprefs2flags(unsigned int srcprefs)
 {
-       /* No need to bitmask because srcprefs have only 3 bits. */
-       return srcprefs << 3;
+       return (srcprefs & IPV6_PREFER_SRC_MASK) << 3;
 }
 
 static inline unsigned int rt6_flags2srcprefs(int flags)
 {
-       return (flags >> 3) & 7;
+       return (flags >> 3) & IPV6_PREFER_SRC_MASK;
 }
 
 static inline bool rt6_need_strict(const struct in6_addr *daddr)
 
        inet6_set_bit(RECVERR6, sk);
 }
 
-static inline int __ip6_sock_set_addr_preferences(struct sock *sk, int val)
+#define IPV6_PREFER_SRC_MASK (IPV6_PREFER_SRC_TMP | IPV6_PREFER_SRC_PUBLIC | \
+                             IPV6_PREFER_SRC_COA)
+
+static inline int ip6_sock_set_addr_preferences(struct sock *sk, int val)
 {
+       unsigned int prefmask = ~IPV6_PREFER_SRC_MASK;
        unsigned int pref = 0;
-       unsigned int prefmask = ~0;
 
        /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
        switch (val & (IPV6_PREFER_SRC_PUBLIC |
                return -EINVAL;
        }
 
-       inet6_sk(sk)->srcprefs = (inet6_sk(sk)->srcprefs & prefmask) | pref;
+       WRITE_ONCE(inet6_sk(sk)->srcprefs,
+                  (READ_ONCE(inet6_sk(sk)->srcprefs) & prefmask) | pref);
        return 0;
 }
 
-static inline int ip6_sock_set_addr_preferences(struct sock *sk, int val)
-{
-       int ret;
-
-       lock_sock(sk);
-       ret = __ip6_sock_set_addr_preferences(sk, val);
-       release_sock(sk);
-       return ret;
-}
-
 static inline void ip6_sock_set_recvpktinfo(struct sock *sk)
 {
        lock_sock(sk);
 
                rcu_read_lock();
                from = rt ? rcu_dereference(rt->from) : NULL;
                err = ip6_route_get_saddr(net, from, &fl6->daddr,
-                                         sk ? inet6_sk(sk)->srcprefs : 0,
+                                         sk ? READ_ONCE(inet6_sk(sk)->srcprefs) : 0,
                                          &fl6->saddr);
                rcu_read_unlock();
 
 
                        return -EINVAL;
                inet6_assign_bit(SNDFLOW, sk, valbool);
                return 0;
+       case IPV6_ADDR_PREFERENCES:
+               if (optlen < sizeof(int))
+                       return -EINVAL;
+               return ip6_sock_set_addr_preferences(sk, val);
        }
        if (needs_rtnl)
                rtnl_lock();
                retv = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
-       case IPV6_ADDR_PREFERENCES:
-               if (optlen < sizeof(int))
-                       goto e_inval;
-               retv = __ip6_sock_set_addr_preferences(sk, val);
-               break;
        case IPV6_RECVFRAGSIZE:
                np->rxopt.bits.recvfragsize = valbool;
                retv = 0;
        }
 
        case IPV6_ADDR_PREFERENCES:
+               {
+               u8 srcprefs = READ_ONCE(np->srcprefs);
                val = 0;
 
-               if (np->srcprefs & IPV6_PREFER_SRC_TMP)
+               if (srcprefs & IPV6_PREFER_SRC_TMP)
                        val |= IPV6_PREFER_SRC_TMP;
-               else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
+               else if (srcprefs & IPV6_PREFER_SRC_PUBLIC)
                        val |= IPV6_PREFER_SRC_PUBLIC;
                else {
                        /* XXX: should we return system default? */
                        val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
                }
 
-               if (np->srcprefs & IPV6_PREFER_SRC_COA)
+               if (srcprefs & IPV6_PREFER_SRC_COA)
                        val |= IPV6_PREFER_SRC_COA;
                else
                        val |= IPV6_PREFER_SRC_HOME;
                break;
-
+               }
        case IPV6_MINHOPCOUNT:
                val = READ_ONCE(np->min_hopcount);
                break;
 
        if (!any_src)
                flags |= RT6_LOOKUP_F_HAS_SADDR;
        else if (sk)
-               flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
+               flags |= rt6_srcprefs2flags(READ_ONCE(inet6_sk(sk)->srcprefs));
 
        return fib6_rule_lookup(net, fl6, NULL, flags, ip6_pol_route_output);
 }